使用 xargs 运行多个命令

使用 xargs 运行多个命令

是否可以使用 find + xargs 来调用多个命令?我正在尝试查找大小大于 100 个字符的所有文件。且少于 1000 个字符,更改其权限并将文件列表打印到文件中。我可以用 exec 来做到这一点,例如

find . -maxdepth 1 -size +100c -size -1000c -exec chmod a+r {} \; -print > testfile

但是有什么办法可以用 xargs 来实现这一点吗?

   find . -maxdepth 1 -size +100c -size -1000c -print0 | xargs -0 -I '{}' chmod a+r '{}' -print >testfile

最后一次打印不会执行或抛出错误。有没有办法用 xargs 来实现它?

答案1

这里不需要任何 GNUism(并且您可能需要-mindepth 1排除.),并且不需要为chmod每个文件运行一个:

find . ! -name . -prune ! -type l -size +100c -size -1000c -print \
  -exec chmod a+r {} + >testfile

(我还添加了一个,! -type l因为-size会检查符号链接的大小,同时chmod会更改目标符号链接,因此考虑符号链接没有意义。您很可能想走得更远,只考虑常规的文件 ( -type f))

这在这里有效,因为chmod不会在其标准输出上输出任何内容(否则最终会出现在测试文件中)。

更一般地说,为了避免这种情况,您需要这样做:

find . ! -name . -prune ! -type l -size +100c -size -1000c -print -exec sh -c '
  exec cmd-that-may-write-to-stdout "$@" >&3 3>&-' sh {} + 3>&1 > testfile 

因此,find's stdout 转到testfilecmd-that-may-write-to-stdout's stdout 转到重定向之前的原始 stdout (如3>&1上面保存的那样)。

请注意,在您的:

find . -maxdepth 1 -size +100c -size -1000c -exec chmod a+r {} \; -print > testfile

testfile将包含已成功的文件chmod-print后面的-exec意思-exec是该的另一个条件-print-exec如果执行的命令以非零退出状态返回,则成功)。

如果你想使用xargs(这里使用 GNU 语法),你可以使用tee并处理替换:

 find . ! -name . -prune ! -type l -size +100c -size -1000c -print0 |
   tee >(tr '\0' '\n' > testfile) |
   xargs -r0 chmod a+r

find将 NUL的输出保存为换行符testfile。但请注意,该tr命令在后台运行。您的 shell 将等待xargs(至少,大多数 shell 也会等待teefind),但不会等待tr。因此,当 shell 运行下一个命令时,很有可能tr已经完成了数据写入。testfile如果testfile到那时完全写入比修改所有权限更重要,您可能需要交换上面的xargstr命令。

另一种选择是将上面的整个代码包装在:

(<that-code>) 3>&1 | cat

这样,shell 将等待cat,并且cat仅当在其读取的管道的写入端打开该文件描述符 3 的所有进程(包括trfindteexargs)退出时才会退出。

另一种选择是在这里使用zshglob:

files=(./*(L+100L-1000^@))
chmod a+r $files
print -rl $files > testfile

虽然你可能会遇到争论太多如果文件列表很大,则会出现错误。find -exec +如果需要,可以xargs通过运行几个命令来解决此问题。您可以使用in来实现这一点。chmodzargszsh

相关内容