在子外壳中bash描述符



下面的摘要旨在聆听并从目录中选择一些歌曲:

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执行的外壳,其中执行了mplayer和Shell read。但这不是!

这里怎么了?

首先,我认为您的困难比必须更难。如果您有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. 打开它。
  3. 您似乎正在尝试更改键盘输入是进行的地方。这很棘手,因为这样做类似于将EOF发送到交互式外壳。大多数贝壳遇到时都会关闭。相反,请考虑更改Xargs获取其输入的位置,然后将键盘放在单位上。(BSD xargs具有相关的-o选项。检查您的manpage。)
  4. 您正在为Mplayer进行相同的重定向,并且无时没有读取。如果您在循环和阅读,您如何知道提供输入时在循环中的位置?

愚蠢的我!应该重定向的是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<&-

如果您想要带有bash的子壳,则可以做到这一点:

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

相关内容

  • 没有找到相关文章

最新更新