5

Well i am really stuck at this one.

I have dirs.txt which is as follows:

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

dirs.txt file is generated by the script itself.

When i want to use dirs.txt in a for loop like:

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

Here is what the command throws: ls: cannot access /var/tmp/old: No such file or directory

I want the whole filenames to be ls -al'ed but it tries to ls -al /var/tmp/old

How may i correct this from the for loop?

4

2 回答 2

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

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

我可能会获得无用猫奖。您可以通过删除以下内容来进一步简化cat

while read dir; do
    ls -al "$dir"
done < dirs.txt

这是有效的,因为整个 while循环就像一个大命令,所以就像你可以通过管道cat进入它一样,你也可以使用文件重定向。


更进一步...

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

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

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

实际上,如果您实际上正在使用find,您可能可以在一个大find命令中完成所有操作,而无需任何循环或任何东西!例如,上面的代码使用findandwhile可以用这样的单个find命令完成:

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

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

于 2009-06-27T16:46:08.467 回答
0

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

但是,对于您的具体问题,我不清楚为什么在目录名之后需要一个文件,而您可能需要在它们之间使用斜杠(即 /var/tmp/old/files.txt)。

但是,您想要执行“ls -al”的事实也不适合。您似乎最终会做的是很多“ls -al /var/tmp/old”(每个 dirs.txt 条目一个),然后是每个本地文件的长列表,如您所示,files.txt和备份.bak。

但是,由于该线程已有将近 2 年的历史,我想您早就解决了这个问题 :)

于 2011-05-04T01:01:16.303 回答