仅复制可执行文件(跨平台)

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.