将 find 命令的结果作为另一个命令的多个选项传递

将 find 命令的结果作为另一个命令的多个选项传递

我有一个 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])

其中Pglob 限定符用于插入参数作为P每个匹配文件的前缀。

使用 GNUfind和 GNUxargs以及支持 ksh 样式进程替换的 zsh 或 bash 等 shell,您还可以执行以下操作:

xargs -xr0 -n100 -a <(find . -name pattern -printf '-I\0%p\0') CLI

100此处选择偶数,希望该偶数足够小,以便参数列表适合单次调用CLI。如果没有它,xargs可以将列表拆分为-I以下文件path。如果它仍然不符合该-n 100约束,则将退出-xxargs而不是CLI使用更少的参数运行。

如果除了 之外还CLI接受,您还可以这样做:-Ipath/to/file-I path/to/file

find . -name pattern -exec bash -c '
  exec CLI "${@/#/-I}"' bash {} +

请注意,虽然是为了在必要时通过多次-exec cmd {} +调用来解决参数大小的限制,但由于 bash向每个参数添加了 a ,所以当它自行执行时,它仍然可能会遇到该限制。cmd-Icmd

但是,由于该前缀的长度-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添加,然后使用这些参数进行调用:-ICLI

#!/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

会做。警告:文件名中的空格和/或特殊字符存在许多问题。

相关内容