对于循环使用查找缺乏不正确处理具有空白字符的目录名称

时间:2009-06-27 16:40:37

标签: bash find whitespace for-loop

好吧,我真的被困在这个。

我有dirs.txt,如下:

/var/tmp/old files.txt
/var/tmp/old backups.bak

dirs.txt文件由脚本本身生成。

当我想在for循环中使用dirs.txt时:

for dir in `cat dirs.txt` ; do 
    ls -al $dir
done

这是命令抛出的内容: ls:无法访问/ var / tmp / old:没有这样的文件或目录

我希望整个文件名都是ls -al'ed但是它会尝试ls -al / var / tmp / old

我如何从for循环中纠正这个问题?

2 个答案:

答案 0 :(得分:12)

cat dirs.txt | while read dir; do
    ls -al "$dir"
done
  1. 使用反引号运算符时,输出会在每个空格字符处拆分为标记。另一方面,read将一次读取一行而不是一次读取一个单词。因此,看起来有点奇怪的解决方案是将文件传输到循环中,以便逐行读取。

  2. 您需要在"$dir"命令中引用ls,以便将整个文件名,空白和所有文件名视为单个参数。如果您不这样做,ls会看到两个文件名,/var/tmp/oldfiles.txt

  3. 我可能会获得Useless Use of Cat Award奖励。您可以通过删除cat

    进一步简化此操作
    while read dir; do
        ls -al "$dir"
    done < dirs.txt
    

    这是有效的,因为整个 while循环就像一个大命令,所以就像你可以将cat传递给它一样,你也可以使用文件重定向。


    更进一步......

    根据dirs.txt的生成方式,您可能只能完全摆脱它并在一个命令中执行所有操作。如果它只是一个临时文件,你可以通过将命令生成dirs.txt直接导入while循环,跳过临时文件来消除它。例如,替换

    find /var -name '*old*' > dirs.txt
    while read dir; do
        ls -al "$dir"
    done < dirs.txt
    

    find /var -name '*old*' | while read dir; do
        ls -al "$dir"
    done
    

    假装find是您为生成文件列表而执行的任何命令。

    实际上,如果你实际上正在使用find,你可以在一个大的find命令中做任何事情而不需要任何循环或任何东西!例如,使用findwhile的上述代码可以使用单个find命令完成,如下所示:

    find /var -name '*old*' -exec ls -al {} \;
    

    find是一个非常灵活的命令,可以搜索匹配各种复杂条件的文件,并使用-exec选项将这些文件作为命令行参数传递给其他命令。当您使用-exec时,{}会被每个文件名替换。

答案 1 :(得分:0)

当我尝试解压缩目录中的大量文件时,我遇到了类似的问题。我发现因为我的“ls”别名,所以我自己造成了不必要的悲伤。一旦我将“ls”完全限定为“/ bin / ls”,一切都与世界相得益彰。

至于你的具体问题,我不清楚为什么你想要一个目录名后面的文件,你可能想要它们之间的斜杠(即/var/tmp/old/files.txt)。 / p>

然而,你想做“ls -al”的事实也不合适。您最终会做的是很多“ls -al / var / tmp / old”(每个dirs.txt条目一个),然后是每个本地文件的长列表,如你已经展示了files.txt和backups.bak。

然而,由于这个帖子将近2年,我想你已经很久没遇到这个问题:)