为什么这个命令执行不成功?
find / -type f -name "*.c" -exec wc -c < \{} \;
我正在尝试隐藏文件名并显示字符数。
find / -type f -name "*.c" -exec wc -c {} + | awk '{print $1}'
<
无法使用,因为重定向应用于find
命令本身。所以你可以使用awk
仅打印第一列。
正如@Charles Duffy指出的那样,这更加高效,因为它意味着我们只启动一个wc
进程和没有shell包装器,每个文件只运行一次(因为awk
实例是共享的,不是每个文件都被调用)。
exec
的 bash 命令。find . -type f -name "*.c" -exec bash -c 'wc -c < "$1"' _ {} \;
<
作用于 find 命令本身,导致出现语法错误,因为没有一个称为 {}
的文件。
编辑
为了不支付调用多个子shell的额外成本,我们可以进一步改进exec
部分,如下所示:
find . -type f -name "*.c" -exec bash -c 'for arg; do wc -c <"$arg"; done' _ {} +
感谢@Charles Duffy提供this建议。
-print0 | while IFS= read -r -d '' name; do wc -c <"$name"; done
这样的命令。目前我们为每个文件启动不仅是一个wc
实例,还有一个bash shell,这导致了很多额外的开销。 - Charles Duffy-exec bash -c 'for arg; do wc -c <"$arg"; done' _ {} +
,将尽可能多的文件名传递给每个 bash 副本。 - Charles Duffy如果你真的想要重定向,你可以在子shell中执行:
find / -type f -name "*.c" -exec sh -c 'wc -c < "{}"' \;
编辑:不要这样做 - 请参见下面的评论!
{}
放在传递给 -c
的参数中会导致安全漏洞。如果有人将 touch '$(rm -rf ~).c'
创建的文件检查到你正在运行的代码库中,你将会度过非常 非常 糟糕的一天。最好将它作为带外传输来传递,就像 sjsam 的答案中所示。 - Charles Duffyfind
的 POSIX 标准不能保证如果 {}
是参数的子字符串而不是整个参数,则会被替换。它适用于常见的实现,包括 GNU 和 BSD,但在旧的或小型嵌入式系统上可能会有问题。) - Charles Duffytouch $'$(rm -rf ~)\'$(rm -rf ~)\'.c'
来创建一个双向攻击的例子)。将数据与代码分离是正确的做法。 - Charles Duffy$(rm
的目录,在其中创建一个子目录tmp
,并在其中创建一个名为test).c
的文件。我的示例没有任何斜杠是有原因的。如果你不想费力去创建一些奇怪命名的目录,可以考虑使用touch $'$(touch pwned)\'$(touch pwned)\'.c'
。 - Charles Duffymkdir -p '$(rm /tmp' && touch '$(rm /tmp/test).c'
(不需要使用 $''
语法,因为我们没有在名称中放置文字单引号)。 - Charles Duffy
wc
иҝӣзЁӢе’ҢжІЎжңүshellеҢ…иЈ…еҷЁ(еӣ дёәawk
е®һдҫӢжҳҜе…ұдә«зҡ„пјҢиҖҢдёҚжҳҜй’ҲеҜ№жҜҸдёӘж–Ү件и°ғз”Ё)гҖӮ - Charles Duffy