2015-05-01 206 views
2

的片段下方的目的是倾听,并从目录中选择了几首歌曲:猛砸描述

exec 3<&1 

find /some/directory -name '*.mp3' -print0 | xargs -0 bash -c ' 
    for i; do 
     mplayer -ss 10 "$i" 1<&3 
     read -p "Select? (y/n)" -n 1 choice 1<&3 
     if [ "$choice" = "y" -o "$choice" = "Y" ]; then 
      echo "$i" > /tmp/selected_songs.txt 
     fi 
    done 
    ' 

exec 3<&- 

的目的是让mplayer和外壳read从键盘接受输入,但ins't锻炼!为此,我认为FD 3将指向findxargs进程的键盘输入。这再次被传递到执行的外壳,其中mplayer和外壳read被执行;但它没有!

这里怎么回事?

+0

你没有说的事情到底如何出了问题,但我会猜测“mplayer”无法响应键盘命令。如果是这种情况,那么它并不一定意味着你的重定向失败 - 这可能意味着'mplayer'使用不同的方法来收集键盘输入,而不是从它的标准输入读取,而且'mplayer'启动时这种方法不起作用来自非交互式shell。特别是,这样的过程没有控制终端。 –

回答

1

傻我!这是FD 0 - 不是1 - 应该重定向。这可以作为一个版本低于预期:

exec 3<&0 
find /media/jeenu/USB/ -type f -print0 | xargs -0 bash -c ' 
    for i; do 
     mplayer -ss 10 "$i" 
     read -p "Select? (y/n/q)" -n 1 choice 
     case "$choice" in 
      [yY]) echo "$i" >> /tmp/selected_songs.txt;; 
      [qQ]) break;; 
     esac 
    done 0<&3 
    ' 
exec 3<&- 
2

首先,我认为你比这更难。如果你有bash 4,请使用globstar。

shopt -s globstar 
for i in /some/directory/**/*.mp3; do 
    mplayer -ss 10 "$i" 
    read -p "Select? (y/n)" -n 1 choice 
    case "$choice" in 
     [yY]) echo "$i" >> /tmp/selected_songs.txt;; 
    esac 
done 

即使你不这样做,你可以使用find … -exec bash -c 'yourscript' _ {} +而不是使用xargs做到这一点。

(我也改变了你的>>>因为我以为你不想截断该文件在每遍。)

对于理解这一问题,有各种复杂的东西去错在这里,但我会指出一些重要的事情:

  1. 标准输入是FD 0,但exec 3<&1重复1至3并打开它阅读
  2. 你似乎试图改变键盘输入。这很棘手,因为这样做与将EOF发送到交互式shell相似。遇到这种情况时,大多数炮弹会关闭。相反,请考虑更改xargs获取输入的位置,并保留键盘。 (BSD xargs有与之相关的-o选项。请检查您的联机帮助页。)
  3. 您正在对mplayer进行同样的重定向,并且没有超时。如果你正在循环阅读,当你提供输入时,你如何知道你在循环中的位置?
+0

我同意它应该是更复杂的。但我更关心如何解决文件描述符在这种情况下的工作原理。是的,那应该是'>>'。谢谢。 – Jeenu

+0

是的,只是意识到它必须是0,而不是1! – Jeenu

0

如果你想使用bash子shell,那么你可以这样做:

find /media/jeenu/USB/ -type f -print0 | xargs -0 bash <<EOF 
#This is a bash subshell 
#put your code here 
EOF