我有一个 CLI 工具,可以采用具有多个值的选项 - 语法如下:
CLI -I path/to/file1 -I path/to/file2 ...
如何将find
命令的结果传递给此 CLI?
以供参考
如果是位置多个参数:
CLI path/to/file1 path/to/file2 ...
我可以:
find "dir" -name "pattern" -exec CLI {} \+
答案1
如果可以zsh
选择切换到,那么可以通过以下方式轻松完成:
CLI **/pattern(P[-I])
其中P
glob 限定符用于插入参数作为P
每个匹配文件的前缀。
使用 GNUfind
和 GNUxargs
以及支持 ksh 样式进程替换的 zsh 或 bash 等 shell,您还可以执行以下操作:
xargs -xr0 -n100 -a <(find . -name pattern -printf '-I\0%p\0') CLI
100
此处选择偶数,希望该偶数足够小,以便参数列表适合单次调用CLI
。如果没有它,xargs
可以将列表拆分为-I
以下文件p
ath。如果它仍然不符合该-n 100
约束,则将退出-x
,xargs
而不是CLI
使用更少的参数运行。
如果除了 之外还CLI
接受,您还可以这样做:-Ipath/to/file
-I path/to/file
find . -name pattern -exec bash -c '
exec CLI "${@/#/-I}"' bash {} +
请注意,虽然是为了在必要时通过多次-exec cmd {} +
调用来解决参数大小的限制,但由于 bash向每个参数添加了 a ,所以当它自行执行时,它仍然可能会遇到该限制。cmd
-I
cmd
但是,由于该前缀的长度-I
恰好与添加到所有文件路径的前缀的长度相同./
,并且我们在这里不需要,因此我们不妨bash
将其替换./
为-I
并完全避免该问题:
find . -name pattern -exec bash -c '
exec CLI "${@/#.\//-I}"' bash {} +
(假设它.
本身(起始文件)与图案)。
上述方法zsh
不会尝试解决execve()
系统调用限制,并且将运行CLI
一次或完全无法运行。可以使用zargs
自动加载功能来解决该限制。
如果每个文件CLI
只调用一次很重要-I file
,那么在现代版本的 Linux 上,提高堆栈大小限制(limit stacksize 100M
例如在 zsh 中将默认值 8MiB 提高)将有所帮助,因为该execve()
限制与堆栈大小成正比限制在那里。
答案2
CLI
从输出中创建一个参数数组,在每个文件名之前find
添加,然后使用这些参数进行调用:-I
CLI
#!/usr/bin/env bash
args=()
while IFS= read -r file; do
args+=( -I "$file" )
done < <(find "dir" -name "pattern" -print)
CLI "${args[@]}"
如果您的文件名可以包含换行符(与您问题中的示例不同),则添加到-d ''
参数read
并使用 GNUfind
并更改-print
为-print0
.
上述假设的内容args[]
不会超过 ARG_MAX。
答案3
作为第一次尝试,
find . -print | sed 's/^/-I /'| xargs echo
会做。警告:文件名中的空格和/或特殊字符存在许多问题。