find -exec 中的 if 命令

find -exec 中的 if 命令

我只是想列出当前目录下的所有目录和文件,并使用以下命令写入它们是否是文件或目录:

find -exec echo `echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi` \;

我知道这是一个愚蠢的命令,我可以使用其他命令,例如-type for -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

相关内容