Bash:如何从命令输出一次读取一行?


49

我正在尝试使用读取bash中命令的输出while loop

while read -r line
do
    echo "$line"
done <<< $(find . -type f)

我得到的输出

ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$ 

在这之后我尝试了

$(find . -type f) | 
while read -r line
do
    echo "$line"
done 

但是它产生了一个错误test.sh: line 5: ./test.py: Permission denied

因此,我如何逐行阅读它,因为我认为当前它一次吞噬了整行。

要求的输出:

./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello

3
我建议阅读Bash FAQ 01-有关避免陷阱的大量有用信息和建议。
2012年

对于这一while read部分,请参阅了解IFS及其链接的问题。
吉尔(Gilles)'所以

Answers:


54

有一个错误,你需要的< <(command)不是<<<$(command)

< <( )是一个Process Substitution$()是一个命令替换<<<是一个here-string


2
@RanRag停止尝试放$( )所有东西!这就是命令替换的语法,这只是使用命令输出的一种方法。管道和进程替换以及此处字符串是其他字符串,它们自然都有不同的语法。除非您真的知道自己在做什么,否则无论如何都不应该解析文件名。
2012年

谢谢,它的工作原理将进一步了解Process Substitution
RanRag 2012年

@ jw013:我是bash初学者。将来,您的建议会铭记在心。
RanRag 2012年

13

请注意,没有什么可以阻止文件名包含换行符的。为每个文件运行一个命令的正规途径发现的发现是。

find . -type f -exec cmd {} \;

如果您希望以bash的方式完成工作:

find . -type f -exec bash -c '
  for file do
    something with "$file"
  done' bash {} +

另外,在脚本中调用“ read”命令的规范方法是(如果您不希望它对输入进行额外的处理):

IFS= read -r var

-r是要停止read特别处理反斜杠字符(作为分隔符和换行符的转义字符),而IFS =则将分隔符列表设置为空字符串read(否则,如果该列表中有空白字符,则它们将从输入的开始和结束)。

在Shell中使用循环通常是个坏主意(不是在Shell中完成工作的方法,在Shell中,要使多个工具共同并发地完成一项任务,而不是依次运行一个或多个工具数百次)。

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.