スペースとカッコを含むパス転送の問題

スペースとカッコを含むパス転送の問題

私はThunar File Explorerを使用し、オーディオ再生のためにパス名とファイル名をスクリプトに渡します。 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::

File:: を角括弧で使ってみました。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したがって、ログインしてリモートシェルを起動して実行すると、引用符なしのplay文字列が表示されるため、スクリプトはスペースをブロックします。 2番目の引用符で囲み、リモートコマンドに引用符を渡すようにします。

これは、i)リモートシステムがシェルshまたはbash同様のものを実行しており、ii)ファイル名に一重引用符が含まれていないと仮定すると機能します。本当に強力にするには、次を参照してください。リモートユーザーのログインシェルを知らず、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? )).

関連情報