子shell

时间:2015-05-01 18:59:29

标签: bash file-descriptor

下面的代码段旨在收听并从目录中选择一些歌曲:

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和shell read接受来自键盘的输入,但是没有成功!为此,我认为FD 3将指向findxargs进程的键盘输入。这又被传递给xargs执行的shell,其中执行了mplayer和shell read;但它没有!

这里出了什么问题?

2 个答案:

答案 0 :(得分: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和读取执行相同的重定向而不会超时。如果你正在循环和阅读,当你提供输入时,你怎么知道你在循环中的位置?

答案 1 :(得分:0)

如果你想要一个带有bash的子shell,那么你可以这样做:

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