*最后答案:
dbus-monitor --profile "interface='net.sacredchao.QuodLibet',member='SongStarted'" |
while read -r line; do
sleep 1
echo -e "$(grep '~filename=' $HOME/.quodlibet/current | sed 's/~filename=//')\n$(python2 -c "import sys, urllib as ul; print ul.unquote_plus(sys.argv[1])" "$(quodlibet --print-queue | sed 's|file://||g')")" > $HOME/Dropbox/Playlists/queue
done在争用条件和破坏多个写的文件方面存在问题,我还用python命令替换了echo -e,因为在使用python生成quodlibet时,它可能首先被解析到了我不想使用python的解析中。现在一切都成功了。我已经给出了大多数音乐播放器已经具备的套话功能:一个队列,实际上是在程序崩溃后幸存下来的,它不需要不断地修补和照看每首歌就能精确地播放一次。叹息
我正在使用Arch,并且我已经制作了一个脚本,它应该在歌曲结束/开始播放时保存quodlibet的队列。除了一件事外,一切都正常工作(所以您不必检查所有sed命令中的错误或其他任何东西)。如果我在终端中手动运行所有这些东西,没有任何while循环或DBus-每次我注意到歌曲结尾时都手动地写入文件--它工作得很好。一旦我将它放入while循环中,每次歌曲开始时,它仍然会写到文件中,但是它每次都会写完全相同的文件,直到我重新启动脚本。我认为这是在缓存这些命令的输出,而不是更新该缓存。
那么,让我们来解释一下: quodlibet有它目前正在播放的歌曲和接下来要播放的内容的队列。下面是剧本:
while read -r line; do
grep '~filename=' $HOME/.quodlibet/current \
| sed 's/~filename=//' > $HOME/Dropbox/Playlists/queue
echo -e "$(quodlibet --print-queue | sed 's|%|\\\x|g' | sed 's|file://||g')" \
>> $HOME/Dropbox/Playlists/queue
done <<< "$(dbus-monitor --profile "interface='net.sacredchao.QuodLibet',member='SongStarted'")"每当一首歌发生变化,这两个命令就会将现在播放的歌曲和队列写到一个文件中。相反,每当一首歌发生变化时,这两个命令就会写出现在播放的歌曲,并在循环第一次写入文件时排队。
因此,假设现在播放的是轨道1和轨道2到10是在队列中。脚本将其写入文件。
然后,第一轨道结束。现在,现在播放是轨道2,队列是曲目3到10。然而,即使循环注意到歌曲的变化并将其写入文件,它所写的却是现在的第1轨道--播放和跟踪2到10作为队列。再来一次。在你还不知道之前,它正在播放第10声道,队列是空的,但是文件中仍然有所有的10首曲目。
当循环脚本运行时,我尝试在循环内部手动运行完全相同的命令,在循环外部的终端中,在歌曲更改后立即运行。文件会反映出它应该做的事。但是当歌曲再次改变时,循环会捕捉到这一点,并重写所有的10首歌曲,再次。换句话说,这些精确的命令只在循环中不执行我想做的事情。在这里,SOMEthing肯定是缓存的,从来没有更新过。
编辑:看起来我需要澄清一些事情。
1)尽管不应该这样做,但我的脚本的行为方式完全相同--无论是:
while read -r line; do
grep '~filename=' $HOME/.quodlibet/current \
| sed 's/~filename=//' > $HOME/Dropbox/Playlists/queue
echo -e "$(quodlibet --print-queue | sed 's|%|\\\x|g' | sed 's|file://||g')" \
>> $HOME/Dropbox/Playlists/queue
done <<< "$(dbus-monitor --profile "interface='net.sacredchao.QuodLibet',member='SongStarted'")"或者:
dbus-monitor --profile "interface='net.sacredchao.QuodLibet',member='SongStarted'" |
while read -r line; do
grep '~filename=' $HOME/.quodlibet/current \
| sed 's/~filename=//' > $HOME/Dropbox/Playlists/queue
echo -e "$(quodlibet --print-queue | sed 's|%|\\\x|g' | sed 's|file://||g')" \
>> $HOME/Dropbox/Playlists/queue
done2)在引入更复杂的内容之前,我测试了一个更简单的版本。这是我写的剧本:
while true; do
echo "$(cat /tmp/foo | sed 's/b/n/g')"
done我试图在循环运行过程中更改文件/tmp/foo,就像quodlibet命令的输出本身发生变化一样,它也进行了很好的更新。输出就像它应该改变的那样。
这不是我开始做的,但这是我在进入实际脚本之前所做的最后一个。您将看到它包含了我正在做的所有事情,除了4件事: quodlibet、dbus命令、>saving或>>appending到一个文件,以及边读边读的组合体。其中之一就是使输出始终保持不变,不管环境中发生了什么变化,我认为我们可以排除引用,因为正如我前面所说的,手动运行这些命令很好。
编辑2:欢迎,我还没有在文件上滚动,但我刚刚做了。这个问题只是变得更复杂,但可能更容易解决。它并不是每次都写完全相同的输出。它以某种方式跳过了覆盖文件的行--以grep开头的行--只是附加了第二行-e的输出。
编辑3:现在我又被困住了。当我从while循环中复制并粘贴准确的两行并放入bash终端时,它们会做我想做的事情。但是在while-循环中,第一个grep命令从未真正写入该文件。我想可能是莫名其妙地吃了第一个命令,所以我试着事先添加一个空的回声:
dbus-monitor --profile "interface='net.sacredchao.QuodLibet',member='SongStarted'" |
while read -r line; do
echo
grep '~filename=' $HOME/.quodlibet/current \
| sed 's/~filename=//' > $HOME/Dropbox/Playlists/queue
echo -e "$(quodlibet --print-queue | sed 's|%|\\\x|g' | sed 's|file://||g')" \
>> $HOME/Dropbox/Playlists/queue
done但它还是在吃第一个grep。为什么它不保存文件?
编辑4:我已经确认grep命令肯定输出了正确的输出,但不会将其写入文件。
发布于 2015-11-22 22:24:48
为了使您想要做的特定事情与您感知到的问题脱钩,我建议您先尝试一些独立的命令,然后再尝试使用任何花哨的命令。
while read -r line ; do
echo $line
done <<< $(yes)注意,这将永远不会输出任何内容。$(yes)提供的输入永远不会完成,因此外部循环将永远不会打印任何内容。至少有一条评论指出了这一点。
不要使用捕获变量,而是尝试将输出直接传递到循环中。我不能说这对您有用,但它至少解决了流输出到while循环的一个明显问题。
yes | while read -r line ; do
echo $line
done根据这里的其他调试工作,问题似乎是关于歌曲转换的dbus信号与新的“当前”歌曲到磁盘的写入之间的竞争条件。为了提供一个更完整的解决方案(当然是未经测试的),我可以从以下几个方面开始:
function urldecode() {
python -c "import sys, urllib as ul; print ul.unquote_plus(sys.argv[1])" "$@"
}
dbus-monitor --profile "interface='net.sacredchao.QuodLibet',member='SongStarted'" | \
while read -r line; do
sleep 1 # Adjust as necessary to preventing race conditions
$CurrentSongFile=$(grep '~filename=' $HOME/.quodlibet/current | sed 's/~filename=//')
$SongFileQueue=$(urldecode "$(quodlibet --print-queue)") | sed 's_file://__g')
printf "$CurrentSongFile\n$SongFileQueue" > $HOME/Dropbox/Playlists/queue
donehttps://stackoverflow.com/questions/33860537
复制相似问题