我试图在for
的输出上使用ls -R
进行迭代,它只是挂起。
for i in $(ls -R /); do echo $i; done;
是一样的
for i in $(find /); do echo $i; done;
问题出在哪里?为什么要保持“光标等待”?
答案 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也支持这种语法