下面的摘要旨在聆听并从目录中选择一些歌曲:
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将指向find
和xargs
进程的键盘输入。再次将其传递给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
进行此操作。
(我也将您的>
更改为>>
,因为我认为您不想在每次通过时截断文件。)
为了理解问题,这里有各种各样的复杂问题,但我会指出一些重要的事情:
- 标准输入为fd 0,但是
exec 3<&1
重复1为3,并为读取。
打开它。
- 您似乎正在尝试更改键盘输入是进行的地方。这很棘手,因为这样做类似于将EOF发送到交互式外壳。大多数贝壳遇到时都会关闭。相反,请考虑更改Xargs获取其输入的位置,然后将键盘放在单位上。(BSD
xargs
具有相关的-o
选项。检查您的manpage。) - 您正在为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