是否可以使用 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 转到testfile
但cmd-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 也会等待tee
和find
),但不会等待tr
。因此,当 shell 运行下一个命令时,很有可能tr
已经完成了数据写入。testfile
如果testfile
到那时完全写入比修改所有权限更重要,您可能需要交换上面的xargs
和tr
命令。
另一种选择是将上面的整个代码包装在:
(<that-code>) 3>&1 | cat
这样,shell 将等待cat
,并且cat
仅当在其读取的管道的写入端打开该文件描述符 3 的所有进程(包括tr
、find
、tee
、xargs
)退出时才会退出。
另一种选择是在这里使用zsh
glob:
files=(./*(L+100L-1000^@))
chmod a+r $files
print -rl $files > testfile
虽然你可能会遇到争论太多如果文件列表很大,则会出现错误。find -exec +
如果需要,可以xargs
通过运行几个命令来解决此问题。您可以使用in来实现这一点。chmod
zargs
zsh