![find -exec 中的 if 命令](https://linux22.com/image/61468/find%20-exec%20%E4%B8%AD%E7%9A%84%20if%20%E5%91%BD%E4%BB%A4.png)
我只是想列出当前目录下的所有目录和文件,并使用以下命令写入它们是否是文件或目录:
find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;
我知道这是一个愚蠢的命令,我可以使用其他命令,例如-type f
or -type d
,但我想了解为什么那段代码没有按我的预期工作。它只是将目录打印到所有这些目录。例如,当 的输出find
是:
.
./dir
./dir/file
我的代码的输出是:
. : directory
./dir : directory
./dir/file : directory
并输出
echo `echo dir/file : ;if [ -f dir/file ]; then echo file; else echo directory;fi`
是
dir/file : file
我正在研究Ubuntu 14.10
和使用find (GNU findutils) 4.4.2
答案1
首先,您的代码片段执行命令
echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi
因为它需要其输出来评估命令替换。由于没有名为 的文件{}
,因此会产生输出
{} :
directory
find
然后使用参数-exec
, echo
, {}
, :
,执行该命令directory
,因此对于每个文件,它都会输出文件名,后跟空格和: directory
。
echo {} :; …
您真正想要做的是在 . 找到的每个文件上执行 shell 片段find
。此代码片段必须由 生成的 shell 执行find
,而不是由启动的 shell执行,因为它是从命令行find
接收数据。find
因此,您需要指示find
运行 shell:
find -exec sh -c 'echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi' \;
这更好了,但仍然不对。如果您的文件名不包含任何特殊字符,它将适用于某些(不是全部)find
实现,但由于您在 shell 脚本中插入文件名,因此您允许文件名执行任意 shell 命令,例如,如果您有一个名为的文件$(rm -rf /)
,然后命令rm -rf /
将被执行。要将文件名传递给脚本,请将它们作为单独的参数传递。
第一个echo
在冒号后打印换行符。使用echo -n
(如果您的 shell 支持)或printf
来避免这种情况。
find -exec sh -c 'printf "%s :" "$0"; if [ -f "$0" ]; then echo file; else echo directory; fi' {} \;
您可以使用-exec … {} +
对 shell 调用进行分组,这样速度更快。
find -exec sh -c 'for x; do printf "%s :" "$x"; if [ -f "$x" ]; then echo file; else echo directory; fi; done' _ {} +
答案2
if; then; else; fi
另一种与 一起执行的方法find
是:
find |
while IFS= read -r p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done