如何随机select一首好久没听的歌并播放
How to randomly select a song I haven't heard in a while and play it
随机播放 mp3 文件通常会导致听到最近播放的曲目。所以我决定使用 'touch' 命令来更新文件的 'last modified' 日期和时间。我希望我的脚本随机 select 从 10 首我最长时间没听过的歌曲中选出一首。
我想到了这个:
ls -t $music_folder | tail -n 10 | sort -R | tail -n 1 | while read file; do
echo $music_folder$file
mplayer $music_folder$file
done
我还没有添加 'touch' 行来更新即将播放的歌曲。
这列出了 $music_folder 中的文件,按上次修改时间排序,只查看最长时间未被触摸的 10 个,将这 10 个的排序顺序随机化,然后抓取一个在列表底部。
'echo' 行完美运行。然而,当我尝试用 mplayer 播放这首歌时,它会尝试播放多个文件,其中每个结果的单词都是不同的文件名。为什么它不将 $file 作为单个文本字符串传递?我怎样才能让 mplayer 播放回显行中显示的文件?
解决方案
在 shell 变量周围加上双引号。例如:
mplayer "$music_folder$file"
讨论
问题在于 bash 与所有其他 POSIX shell 一样,对未加引号的 shell 变量执行路径名扩展和分词。为了说明,让我们在一个包含三个文件的目录中工作:
$ ls
1.mp3 2.mp3 3.mp3
现在,让我们定义一个变量并扩展它没有引用:
$ var="dir/Joe's song *.mp3"
$ printf "%s\n" $var
dir/Joe's
song
1.mp3
2.mp3
3.mp3
观察到dir/Joe's
和song
是分开的:这就是分词。此外, *.mp3
成为目录中的文件列表:这是路径名扩展。然而,这两者都可以通过使用双引号来抑制:
$ printf "%s\n" "$var"
dir/Joe's song *.mp3
这就是你想要的。
为了完整性,让我们考虑单引号:
$ printf "%s\n" '$var'
$var
在单引号内,shell 不展开任何内容。因此,如上所示,偶数四个字符$var
保持不变。
随机播放 mp3 文件通常会导致听到最近播放的曲目。所以我决定使用 'touch' 命令来更新文件的 'last modified' 日期和时间。我希望我的脚本随机 select 从 10 首我最长时间没听过的歌曲中选出一首。
我想到了这个:
ls -t $music_folder | tail -n 10 | sort -R | tail -n 1 | while read file; do
echo $music_folder$file
mplayer $music_folder$file
done
我还没有添加 'touch' 行来更新即将播放的歌曲。
这列出了 $music_folder 中的文件,按上次修改时间排序,只查看最长时间未被触摸的 10 个,将这 10 个的排序顺序随机化,然后抓取一个在列表底部。
'echo' 行完美运行。然而,当我尝试用 mplayer 播放这首歌时,它会尝试播放多个文件,其中每个结果的单词都是不同的文件名。为什么它不将 $file 作为单个文本字符串传递?我怎样才能让 mplayer 播放回显行中显示的文件?
解决方案
在 shell 变量周围加上双引号。例如:
mplayer "$music_folder$file"
讨论
问题在于 bash 与所有其他 POSIX shell 一样,对未加引号的 shell 变量执行路径名扩展和分词。为了说明,让我们在一个包含三个文件的目录中工作:
$ ls
1.mp3 2.mp3 3.mp3
现在,让我们定义一个变量并扩展它没有引用:
$ var="dir/Joe's song *.mp3"
$ printf "%s\n" $var
dir/Joe's
song
1.mp3
2.mp3
3.mp3
观察到dir/Joe's
和song
是分开的:这就是分词。此外, *.mp3
成为目录中的文件列表:这是路径名扩展。然而,这两者都可以通过使用双引号来抑制:
$ printf "%s\n" "$var"
dir/Joe's song *.mp3
这就是你想要的。
为了完整性,让我们考虑单引号:
$ printf "%s\n" '$var'
$var
在单引号内,shell 不展开任何内容。因此,如上所示,偶数四个字符$var
保持不变。