
私は単純なbashスクリプトを持っています。基本的に、ファイルがリモートシステムに存在することを確認したいと思います。これを行う方法の多くの例を見つけましたが、欠落しているコンポーネントはこれを行う方法です。スペース評価されるパスおよび/またはファイル名にあります。
#!/bin/bash
HOST=server.local
DIR=/foo/bar
FILE="Foo Bar File With Spaces"
if ssh $HOST [[ -f ${DIR}/${FILE} ]]
then
echo "The file exists"
else
echo "The file doesn't exist."
fi
だから失敗しました。条件式に構文エラーが発生します。ただし、FILE変数を次のように変更した場合:
FILE="Foo\ Bar\ File\ With\ Spaces"
スクリプトが機能します(ファイルがあるため検索します)。
条件式の次の変形を試みた。
if ssh $HOST [[ -f "${DIR}/${FILE}" ]]
そして
if ssh $HOST [[ -f "${DIR}"/"${FILE}" ]]
どちらも機能しません。私は簡単なものを見逃していることを知っています。誰かが私に正しい方向を教えてもらえますか?
答え1
引用符の追加を追加することで、1つはローカルシェル用で、もう1つはローカルシェルです。離れてシェルを実行していますssh
。
$ dir=/tmp; file="foo bar";
$ ssh somewhere ls -l "'$dir/$file'"
-rw-r--r-- 1 foo foo 4194304 Oct 19 18:05 /tmp/foo bar
$ ssh somewhere [[ -f "'$dir/$file'" ]] ; echo $?
0
ssh
コマンドが実行される前に、ローカルシェルが変数を拡張するように外部で二重引用符を使用しようとしています。内部一重引用符のため、リモートシェルは特殊文字を拡張しなくなりました。
ファイル名に一重引用符が含まれていない場合。このような場合は悩みに陥ります。
この問題を解決するには、文字列に必要なエスケープ文字を追加する必要があります。一部のシステムにはこの機能があり、printf "%q"
新しいバージョンの Bash にはこの機能があります。${var@Q}
拡張同様のことが行われるべきです。
$ dir=/tmp; file="\$foo' bar"
$ fullpath="$(printf "%q" "$dir/$file")"
$ ssh somewhere ls -l "$fullpath"
-rw-r--r-- 1 foo foo 0 Oct 19 18:45 /tmp/$foo' bar
答え2
私がこれをお勧めするかどうかはわかりませんが、サーバー管理者および/またはシステム/配布がセキュリティに興味がない限りできる(一般的に)少数の環境変数の1つを乱用すると、次のようにssh
なります。
export LC_MESSAGES='path/to/file with spaces'
if ssh $host '[ -f "$LC_MESSAGES" ]' ; then ...