bash循环文件神秘错误

时间:2019-07-17 14:29:27

标签: bash while-loop stdin mplayer

谁能告诉我这是怎么回事:

此:

find . -name "*.mp3" | while read fname ; do 
    echo "$fname"; 
    ls -l "$fname"; 
    echo mplayer "$fname" ; 
    echo "$fname" ;
done
就我所见,

绝对可以正常工作,但是如果我实际上尝试运行mplayer而不是回显命令:

find . -name "*.mp3" | while read fname ; do 
     echo "$fname"; 
     ls "$fname"; 
     mplayer "$fname" ; 
     echo "$fname" ; 
done

然后播放一个文件,然后转为干草。

我认为mplayer必须以某种方式与阅读交互,但是在bash方面我并不明智。

3 个答案:

答案 0 :(得分:3)

使用-noconsolecontrols的{​​{1}}选项。它使它忽略标准输入,因此它不会从中窃取字符并且mplayer可以处理它们,并且read的行为也不会奇怪,它们将文件名解释为来自键盘的命令。 / p>

答案 1 :(得分:2)

您的猜测是正确的。 find将其文件列表输出到stdout。您将其传送到第二个进程:while循环。在此循环中,readmplayer都从stdin中读取。 read将读取第一个文件名,而mplayer将读取所有其余输入,就像您在运行时通过键盘对其进行控制一样。

最简单的解决方案是在mplayer之后添加</dev/null,但是如果无法从stdin中读取,可能会很不高兴。其他解决方案是为find | read部分使用单独的文件描述符,或者使用for循环。

答案 2 :(得分:2)

执行此操作:

#!/bin/env bash
while IFS= read -r -d '' fname <&9; do 
     printf '%s\n' "$fname"
     ls "$fname"
     mplayer "$fname"
     printf '%s\n' "$fname"
done 9< <(find . -name '*.mp3' -print0)

请参见http://mywiki.wooledge.org/BashFAQ/001