以下代码对所有类型为
do_x.sh
的文件递归执行 a_???.json
。但是,我想对这些文件的子集执行相同的操作,这些文件没有具有相同名称和不同扩展名的相应文件。
find $PWD -type f -name "a_???.json" | xargs -I{} do_x.sh {}
我该如何在同一句话中说,做同样的事情,但只对没有相应
a_???.json
的文件 a_???.json
完成?以下不是确定的解决方案:
find $PWD -type f -name "a_???.json" -exclude "a_???.json.done" | xargs -I{} do_x.sh {}
Example
a_111.json
a_112.json
a_111.json.done
因此,仅在
do_x.sh
上执行
a_112.json
要保持脚本的相同结构,请尝试以下操作:
find $PWD -type f -name "a_???.json" -execdir bash -c 'test ! -f {}.done' \; -print | xargs -I{} do_x.sh {}
您可以使用
xargs
通过命令bash -c
运行shell代码。这允许您使用同一命令处理多个 find
点击,如果您有很多文件,这可能会带来显着的性能改进:
find "$PWD" -type f -name "a_???.json" -print0 |
xargs -0 -r bash -c 'for f; do [[ -e "${f}.done" ]] || do_x.sh "$f"; done' bash
为了便于阅读,我将其分成两行,但它是一条管道。
请注意,没有显式参数项的
for
循环会在位置参数上运行,这就是 shell 从 find
接收文件名的方式。
另请注意,尾随的
bash
是有意且必要的,或者至少在该位置需要 something,否则 find
发出的第一个文件将被用作 shell 的 $0
,其中命令运行。
在
if
中执行 shell xargs
语句。
find "$PWD" -type f -name "a_???.json" -exec bash -c 'if ! [ -f "$1.done" ]; then do_x.sh "$1"; fi' {} {} \;
不需要使用
xargs
,您可以使用-exec
关键字到find
来执行命令。
由于
-exec
不使用 shell 来执行命令,因此您必须显式执行 bash -c
。
对于更复杂的命令,它是类似的。使用
xargs
获取并行操作,然后将完整命令放入 then
的 if
子句中。
find "$PWD" -type f -name "a_???.json" |
xargs -I{} -n1 -P10 bash -c 'if ! [ -f "$1.done" ]; then srun -N1 -A goc -p slurm do_x.sh "$1"; fi' {} {} \;