我使用 Thunar 文件资源管理器并将路径名和文件名传递给脚本音频播放。 Audioplay 通过 ssh 在我的 Android 上运行播放命令来播放歌曲。
音频播放脚本::cat audioplay
if [ $# -eq 1 ] ; then
echo " Playing..." "$@"
sshpass -p $passwd ssh [email protected] -p $port play "$@"
else
echo " No Input audio file."
fi
在我的 Android 上播放脚本 ::cat play
#!/data/bin/bash
# Avoid linker errors due to libOpenSLES.so:
echo "File ::" "$@"
LD_LIBRARY_PATH= exec /data/bin/blob/play-audio "$@"
问题是路径未正确传递到通过 ssh 播放命令。具有多个空格的路径变成单个空格,并且括号会产生语法错误。
例子 :
对于 18. Warriors.flac
存在于/sdcard/Music/Imagine Dragons - Smoke Mirrors -Deluxe Edition-2015
发送到audioplay的路径是正确的::/sdcard/Music/Imagine Dragons - Smoke Mirrors -Deluxe Edition-2015/18. Warriors.flac
但是播放脚本接收到的路径是错误的::/sdcard/Music/Imagine Dragons - Smoke Mirrors -Deluxe Edition-2015/18. Warriors.flac
多个空格变成了单个空格。为什么 ?
然后主二进制文件仅获取到第一个空间的play-audio
路径。/sdcard/Music/Imagine
示例 2::
我尝试使用带有方括号的文件 ::44. Go Tell Aunt Rhody -Resident Evil- (Short Version).flac
音频播放脚本收到的路径是正确的 ::/sdcard/Music/44. Go Tell Aunt Rhody -Resident Evil- (Short Version).flac
但我收到此错误 ::sh: syntax error: '(' unexpected
我尝试通过$@
$*
"$@"
和"$*"
。但他们都不适合我。
答案1
再次引用一下:
if [ "$#" -eq 1 ] ; then
echo " Playing..." "$1"
sshpass -p "$passwd" ssh [email protected] -p "$port" "play '$1'"
else
echo " No Input audio file."
fi
问题是,"$@"
当您运行sshpass
命令时,第一层引号会展开。因此,当您登录、启动远程 shell 并执行时play
,您会得到一个不带引号的字符串,因此您的脚本会因空格而阻塞。通过将其括在第二层引号中,可以确保将其带引号传递给远程命令。
假设 i) 远程计算机正在运行sh
或bash
类似的 shell 以及 ii) 您的文件名不包含单引号,这应该可以工作。为了使其真正强大,请参阅如何在不知道远程用户的登录 shell 的情况下通过 ssh 执行任意简单命令?。
为了在语法中正确引用任意字符串(甚至是任意字符串列表,以便您可以向 传递多个参数play
)sh
,我们可以使用shquote()
此处提到的函数:
shquote() {
LC_ALL=C awk -v q=\' -v b='\\' '
BEGIN{
for (i=1; i<ARGC; i++) {
gsub(q, q b q q, ARGV[i])
printf "%s ", q ARGV[i] q
}
print ""
exit
}' "$@"
}
if [ "$#" -ge 1 ] ; then
echo " Playing..." "$@"
sshpass -p "$passwd" ssh [email protected] -p "$port" "play $(shquote "$@")"
else
echo " No Input audio file."
fi
它会引用Sgt. Pepper's lonely hearts club band.flac
哪个'Sgt. Pepper'\''s lonely hearts club band.mp3'
是正确的sh
(并且evil';reboot;: '.flac
作为'evil'\'';reboot;: '\''.flac'
而不是重新启动远程计算机(您有运行该play
命令作为root
?))。