if命令在find -exec中


10

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

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

我知道这是一个愚蠢的命令,我可以使用诸如-type f或的其他方式-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
find -exec bash -c 'echo -n "{} : ";if [ -f "{}" ]; then echo file; else echo directory;fi' \;
Costas

1
感谢@Costas,但我知道使用bash或sh可以达到我的最初目标,但是现在我想了解为什么exec参数的行为不同。
Esref

将参数放在引号中"{}"。为什么要使用echo两次?
Costas

我已经尝试过了,它给出了相同的输出。找到-exec echo echo "{}" : ;if [ -f "{}" ]; then echo file; else echo directory;fi\;
Esref

Answers:


13

首先,您的代码段执行命令

echo {} : ;if [ -f {} ]; then echo file; else echo directory;fi

因为它需要其输出来评估命令替换。由于没有名为的文件{},因此产生输出

{} :
directory

然后,find命令与参数执行-exececho{}:directory,所以对于每一个文件,它输出的文件名,后跟一个空格和: directory

您真正想要做的是对所echo {} :; …找到的每个文件执行shell片段find。此代码段必须由产生的外壳执行find,而不是由启动的外壳执行find,因为它正在find从命令行接收数据。因此,您需要指示find运行外壳程序:

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

这更好,但仍然不正确。find如果您的文件名不包含任何特殊字符,它将与某些(不是全部)实现一起使用,但是由于您是在Shell脚本中插入文件名,因此您可以允许文件名执行任意的Shell命令,例如$(rm -rf /)然后rm -rf /将执行一个名为的文件。要将文件名传递给脚本,请将它们作为单独的参数传递。

同样,第echo一个在冒号之后打印换行符。使用echo -n(如果您的外壳支持)或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' _ {} +

3

if; then; else; fi与一起执行的另一种方式find是:

find |
while read p; do if [ -f "$p" ]; then echo file; else echo directory; fi; done

1
很酷的解决方案。它避免了复杂的报价模式和subshel​​l复杂性。您可能之前已经定义了一个shell函数,然后在符合“ if”条件的文件上执行它。
盖洛斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.