除非我在

时间:2015-12-28 18:47:36

标签: bash fish

编辑:我不知道这个问题是否会得到解决,但它可能不再重要。我还asked the quodlibet team for help,他们立即修复程序以允许转义逗号,然后告诉我~/.quodlibet/control file(这是为我修复的内容)。

所以,我正在运行一个命令来自动将文件列表排入quodlibet(一个音乐播放器):我已经用bash和fish测试了它。

quodlibet --enqueue-files="\"$(tail -n +2 $HOME/Dropbox/Playlists/queue | sed ':a;N;$!ba;s|\n|","|g')\""

和鱼的版本是:

quodlibet --enqueue-files=\"(tail -n +2 $HOME/Dropbox/Playlists/queue | sed ':a;N;$!ba;s|\n|","|g')\"

我很高兴使用这个确切的bash命令已经有几个星期了,而且它一直很好用。然而,它突然停止工作。这是最奇怪的部分。我有两台运行Arch Linux的计算机。有一个我经常更新,桌面,以及一个我没有打扰升级很长一段时间,笔记本电脑。它有较旧版本的quodlibet,bash和fish。我只用我的笔记本电脑离开了一段时间,并愉快地使用这个命令。但是,几天前,如果没有我升级或改变有关quodlibet,bash,fish,命令甚至整个系统的任何内容,它突然停止工作。我现在已经回到升级后的桌面上了,它现在也无法正常工作,好像整个问题都是基于系统时钟等。

那究竟是怎么回事呢?好吧,它绝对没有任何东西,并且没有输出任何输出。它应该吐出没有输出,如果它工作,但它不工作,似乎没有错误。但是,这里有更奇怪的地方。它实际上仍然可以正常工作,如果我把它分成两个命令。如果我跑

echo "\"$(tail -n +2 $HOME/Dropbox/Playlists/queue | sed ':a;N;$!ba;s|\n|","|g')\""

然后复制输出并将其粘贴到quodlibet --enqueue-file =中,它可以正常工作。

示例:假设文件$ HOME / Dropbox /播放列表/队列中有3个音乐文件:

/home/jimi/Music/Song1.mp3
/home/jimi/Music/Song2.mp3
/home/jimi/Music/Song3.mp3

字符串“\”$(tail -n +2 $ HOME / Dropbox / Playlists / queue | sed':a; N; $!ba; s | \ n |“,”| g')\“”将其评估为

"/home/jimi/Music/Song2.mp3","/home/jimi/Music/Song3.mp3"

(由于不同的命令,第一首歌开始播放,而不是入队。)如果我尝试将字符串“\”$(尾部-n + 2 $ HOME / Dropbox /播放列表/队列| sed'排队:a; N; $!ba; s | \ n |“,”| g')\“”,它几天前一直工作,但它不起作用。但是,如果我手动粘贴“/home/jimi/Music/Song2.mp3","/home/jimi/Music/Song3.mp3”,它可以正常工作。我不知道为什么会这样。我已经完成了一系列测试,试图找出它并且无处可去。我做过的主要注意事项的两个测试是在鱼中尝试找到完全相同的行为,然后尝试

quodlibet --enqueue-files=$(echo "\"$(tail -n +2 $HOME/Dropbox/Playlists/queue | sed ':a;N;$!ba;s|\n|","|g')\"")
因为它似乎非常喜欢echo的输出。但是,都没有工作。最后,quodlibet决定只接受我自己手动输入的文件,尽管由于bash的工作方式,它不应该能够判断我是否自己键入了它。

编辑:新消息:报价是问题的根源。如果我跑

quodlibet --enqueue-files="$(tail -n +2 $HOME/Dropbox/Playlists/queue | sed ':a;N;$!ba;s|\n|,|g')"

它有效。有什么不同?好吧,该字符串避免在sed字符串中包含任何引号。我知道它特别是sed引号(sed':a; N; $!ba; s | \ n |“,”| g')因为我已经在没有其他引号的情况下测试了它。无论如何,sed引用。当我删除它,它的工作原理。这不是一个可行的解决方案,因为为了使quodlibet不会误解任何在其文件名中包含逗号的歌曲,我需要那些引号。我无法逃脱逗号 - 它不接受这一点。所以,我试过这个:

\"$(tail -n +2 $HOME/Dropbox/Playlists/queue | sed ':a;N;$!ba;s|\n|\",\"|g')\"

但这也行不通!似乎quodlibet不接受任何在sed线上引用的东西!当我用转义的单引号尝试它时,bash会给我一个换行符,好像命令没有输出完毕。

1 个答案:

答案 0 :(得分:1)

我不认为你做对了。我必须承认我不认识Fish,但对于Bash,你所说的并不是真的有意义。

当你粘贴" ..."时,shell会剥离引号。证人:

vnix$ printf '>>%s<<\n' "/home/jimi/Music/Song2.mp3","/home/jimi/Music/Song3.mp3"
>>/home/jimi/Music/Song2.mp3,/home/jimi/Music/Song3.mp3<<

如果你真的,真的想保留那些引号,你需要转义,或以某种方式插入它们。也许是这样的:

vnix$ printf '>>%s<<\n' '"/home/jimi/Music/Song2.mp3","/home/jimi/Music/Song3.mp3"'
>>"/home/jimi/Music/Song2.mp3","/home/jimi/Music/Song3.mp3"<<

现在,单引号保护双引号不被shell处理,因此它们会通过printf命令的参数。

假设您希望Quod Libet看到每个文件名周围的文字引号,您可以从文件中读取它们,如下所示:

quodlibet --enqueue-files="$(sed '1d;:a;N;$!ba;s|\n|","|g;s/.*/"&"/' $HOME/Dropbox/Playlists/queue)"

(我冒昧地将tail分解出来,因为sed可以删除第一行就好了。)尝试使用printf来查看我们在这里得到的内容:< / p>

vnix$ printf '>>%s<<\n' quodlibet --enqueue-files="$(sed -e 1d \
    -e ':a' -e 'N' -e '$!ba' -e 's|\n|","|g' -e 's/.*/"&"/' quodlibet)"
>>quodlibet<<
>>--enqueue-files="/home/jimi/Music/Song2.mp3","/home/jimi/Music/Song3.mp3"<<

(我的狡猾BSD sed不喜欢跳转标签中的分号,似乎?)

shell使用外部双引号,sed脚本现在提供我们需要参数实际包含的所有文字引号。

我不相信这会有效,但它应该为您出现提出的问题提供答案。