仅复制可执行文件(跨平台)
Copy only executable files (cross platform)
我想将可执行文件从一个目录复制到另一个目录。
源目录包含各种我不关心的文件(构建工件)。我只想获取可执行文件,使用适用于 OS X 和 Linux.
的 bash 脚本
所谓可执行文件,是指具有可执行权限的文件,会通过test -x $filename
。
我知道我可以写一些 python 脚本,但我会引入对 python 的依赖(只是为了复制文件!)这是我真正想避免的事情。
注意:我似乎遇到了几个类似的问题,但答案似乎只适用于 Linux(因为问题专门针对 Linux 提出)。请不要将其标记为重复,除非重复的问题确实只是关于可执行文件的跨平台复制。
经过一些实验,这似乎适用于 OS X 和 Ubuntu
find "$src_dir" -maxdepth 1 -type f -exec test -x {} \; -exec cp {} "$dest_dir/" \;
请注意,-maxdepth 1
特定于我的用例,我不关心递归遍历所有目录。
-type f
是必需的,因为目录也算作可执行文件
我传递了两个 -exec
标志。 exec 标志不仅执行命令,还算作过滤器,因此如果命令 returns 非零退出代码,则文件被过滤掉。
使用exec的方法是写出你想要的任何命令,使用{}
提供当前文件,并以\;
结束
第一个 -exec
returns 仅当文件可执行时才为成功退出代码。
第二个 -exec
执行复制,但如果第一个 -exec
失败则不会执行。
在概念上很优雅,但速度很慢,因为它至少为每个输入文件 (test
) 创建一个子进程,再加上每个 匹配 文件 (cp
).
这是一个更有效的bash
替代方案:
- 在 shell 代码中构建一个 数组 匹配输入文件,
- 然后使用 单次 调用
cp
. 复制它们
#!/usr/bin/env bash
exeFiles=()
for f in "$src_dir"/*; do [[ -x $f && -f $f ]] && exeFiles+=( "$f" ); done
cp "${exeFiles[@]}" "$dest_dir/"
exeFiles=()
初始化存储匹配文件名的数组。
for f in "$src_dir"/*
遍历直接位于 $scr_dir
中的所有文件和目录;请注意 *
必须如何 不加引号 才能发生通配(文件名扩展)。
[[ -x $f && -f $f ]]
确定手头的项目是否可执行 (-x
) 和(常规)文件 -f
;请注意,[[ ... ]]
中的双引号变量引用(大部分)是可选的。
exeFiles+=( "$f" )
向数组追加一个新元素
"${exeFiles[@]}"
将生成的数组作为一个整体引用,并作为单独的参数稳健地扩展为数组元素 - 参见 Bash arrays.
我想将可执行文件从一个目录复制到另一个目录。
源目录包含各种我不关心的文件(构建工件)。我只想获取可执行文件,使用适用于 OS X 和 Linux.
的 bash 脚本所谓可执行文件,是指具有可执行权限的文件,会通过test -x $filename
。
我知道我可以写一些 python 脚本,但我会引入对 python 的依赖(只是为了复制文件!)这是我真正想避免的事情。
注意:我似乎遇到了几个类似的问题,但答案似乎只适用于 Linux(因为问题专门针对 Linux 提出)。请不要将其标记为重复,除非重复的问题确实只是关于可执行文件的跨平台复制。
经过一些实验,这似乎适用于 OS X 和 Ubuntu
find "$src_dir" -maxdepth 1 -type f -exec test -x {} \; -exec cp {} "$dest_dir/" \;
请注意,-maxdepth 1
特定于我的用例,我不关心递归遍历所有目录。
-type f
是必需的,因为目录也算作可执行文件
我传递了两个 -exec
标志。 exec 标志不仅执行命令,还算作过滤器,因此如果命令 returns 非零退出代码,则文件被过滤掉。
使用exec的方法是写出你想要的任何命令,使用{}
提供当前文件,并以\;
第一个 -exec
returns 仅当文件可执行时才为成功退出代码。
第二个 -exec
执行复制,但如果第一个 -exec
失败则不会执行。
test
) 创建一个子进程,再加上每个 匹配 文件 (cp
).
这是一个更有效的bash
替代方案:
- 在 shell 代码中构建一个 数组 匹配输入文件,
- 然后使用 单次 调用
cp
. 复制它们
#!/usr/bin/env bash
exeFiles=()
for f in "$src_dir"/*; do [[ -x $f && -f $f ]] && exeFiles+=( "$f" ); done
cp "${exeFiles[@]}" "$dest_dir/"
exeFiles=()
初始化存储匹配文件名的数组。for f in "$src_dir"/*
遍历直接位于$scr_dir
中的所有文件和目录;请注意*
必须如何 不加引号 才能发生通配(文件名扩展)。[[ -x $f && -f $f ]]
确定手头的项目是否可执行 (-x
) 和(常规)文件-f
;请注意,[[ ... ]]
中的双引号变量引用(大部分)是可选的。exeFiles+=( "$f" )
向数组追加一个新元素
"${exeFiles[@]}"
将生成的数组作为一个整体引用,并作为单独的参数稳健地扩展为数组元素 - 参见 Bash arrays.