在$(命令)中使用bash的正确方法是什么?

时间:2012-06-10 18:50:04

标签: bash for-loop

我试图在for的输出上使用ls -R进行迭代,它只是挂起。

for i in $(ls -R /); do echo $i; done;

是一样的
for i in $(find /); do echo $i; done;

问题出在哪里?为什么要保持“光标等待”?

4 个答案:

答案 0 :(得分:3)

它暂停的原因是因为首先将$()视为要首先计算的变量。所以它首先进行查找并将所有内容加载到内存中,然后迭代它。

无论如何,对一个发现进行循环往往是一个坏主意。即使是少量商品。 bash for循环将所有空格视为项的分隔符。这意味着如果您的任何文件名包含空格,您将得到不良结果。相反,我建议使用find的内置exec选项。

find / -exec echo '{}' \;


正如Karthik指出的那样,你也可以使用带有read的while循环。

ls -R / | while read i; do
    echo $i
done

这个循环有两个原因。首先,读取仅在\ n(或EOF)上中断。这意味着具有空格的文件将被计为一个文件。其次,管道确保数据不会积累。文件名将被循环吃掉,因为它们是由 ls 生成的。

答案 1 :(得分:3)

“查找”以外的答案

解析ls的输出通常是个坏主意。其他人已经向您展示了如何使用find。你在bash中有另一个选择:globstar。

shopt -s globstar
for file in /tmp/**; do
    echo "$file"
done

另请参阅

答案 2 :(得分:2)

这是因为变量被读取,加载到for中。

有时,bash无法在内部处理那么多变量。尝试使用这些替代方案以获得最佳效果。

请尝试这些:

#IO based is best.
ls -R / | while read i ; do
  echo $i
done

(或)

#in your case
find / -exec echo \{\} \;

答案 3 :(得分:1)

这取决于你想在循环中做什么。管道进入while循环的问题是循环内部的任何变量都不可见。例如:

x=0
ls -R / | while read i; do
    (( x++ ))
done
echo $x

会给0(顺便说一下,ksh没有这个问题)。解决方案是使用Process Substitution,它使用命名管道一次提供一行,这次循环以内联方式运行:

x=0
while read i; do
    (( x++ ))
done < <(ls -R /)
echo $x

ksh93也支持这种语法