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

Ran*_*Rag 63 shell bash pipe find

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

while read -r line
do
    echo "$line"
done <<< $(find . -type f)
Run Code Online (Sandbox Code Playgroud)

我得到的输出

ranveer@ranveer:~/tmp$ bash test.sh
./test.py ./test1.py ./out1 ./test.sh ./out ./out2 ./hello
ranveer@ranveer:~/tmp$ 
Run Code Online (Sandbox Code Playgroud)

在这之后我试过了

$(find . -type f) | 
while read -r line
do
    echo "$line"
done 
Run Code Online (Sandbox Code Playgroud)

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

那么,我如何逐行阅读它,因为我认为目前它正在一次吞食整行。

所需输出:

./test.py
./test1.py
./out1
./test.sh
./out
./out2
./hello
Run Code Online (Sandbox Code Playgroud)

Gil*_*not 74

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

< <( )是一个进程替换$()是一个命令替换<<<是一个here-string


Sté*_*las 14

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

find . -type f -exec cmd {} \;
Run Code Online (Sandbox Code Playgroud)

如果你想在 bash 中完成事情:

find . -type f -exec bash -c '
  for file do
    something with "$file"
  done' bash {} +
Run Code Online (Sandbox Code Playgroud)

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

IFS= read -r var
Run Code Online (Sandbox Code Playgroud)

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

在 shell 中使用循环通常是一个坏主意(而不是在 shell 中如何让多个工具共同并发地工作,而不是按顺序运行一个或多个工具数百次)。


ᄂ ᄀ*_*ᄂ ᄀ 12

如果您想使用管道,则无需命令替换。默认情况下read从读取stdin,所以你只需管道进入它:

find . -type f -print0 |
while read -r -d '' line
do
    echo "$line"
done
Run Code Online (Sandbox Code Playgroud)

或在一行

find . -type f -print0 | while read -r -d '' line; do echo "$line"; done
Run Code Online (Sandbox Code Playgroud)

使用-print0-d ''是针对文件名中潜在换行符的保护措施,默认情况下表示行尾为read(可以使用 更改-d)。''上面使用的实际上是空字节 in bash(相当于$'\0')。

另一个已经提到的方法是使用find's-exec选项。这很可能是性能方面的最佳选择(记住使用-exec cmd {} +变体,这样它就不会为正在处理的每一行分叉一个进程)。但这实际上取决于您在while循环中执行的操作以及处理的数据量。对于您的情况,差异可能可以忽略不计或可以接受。