私はUbuntuを実行しているローカルホストとリモートホストがあり、シェルはbashに設定されています。私のホームディレクトリには、ローカルホストとリモートホストに2つのファイルがfile-1
あります。各ホームディレクトリにはいくつかの異なるファイルがあり、一致するファイルのみをリストしたいと思います。file-2
remote
file-*
ローカルでは、次の予測結果が生成されますfile-1 file-2
。
$ ls file-*
$ bash -c 'ls file-*'
ただし、このコマンドはリモートホームディレクトリ内のすべてのファイルを返します。そこで何が起こったの?
$ ssh remote bash -c 'ls file-*'
$ ssh remote bash -c 'ls "file-*"'
$ ssh remote bash -c 'ls file-\*'
$ ssh remote bash -c 'ls "file-\*"'
ssh remote 'ls file-*'
これが期待した結果だけを生成することを知っていますが、渡されたssh remote bash -c 'ls ...'
引数が破棄されたように見えるのはなぜですかls ...
? (リモートで実行されたlsの出力もパイプして渡されたため、ls
その出力のみ影響を受けるようですssh remote bash -c 'ls file-* | xargs -I {} echo "Got this: {}"'
。)
ベストアンサー1
使用時にリモートホストで実行されるコマンドはssh remote bash -c 'ls file-*'
次のとおりです。
bash -c ls file-*
これはbash -c
スクリプトを実行することを意味しますls
。位置引数として、bash -c
スクリプトはリモートホストから一致する名前を取得しますfile-*
(これらの名前の最初の名前はに置かれるため、$0
実際には位置引数の一部ではありません)。引数はコマンドに渡されないため、ls
ディレクトリ内のすべての名前が一覧表示されます。
ssh
最初のレベルの引用符(コマンドラインで使用される一連の外部引用符)を削除し、リモートホストで実行するコマンドを渡します。呼び出されたシェルはssh
これらの引用符を削除し、ssh
リモートコマンドの引数を区別するために新しい引用符を挿入しません(コマンドで使用される引用符を中断する可能性があるため)。
次のコマンドを使用してこれを確認できますssh -v
。
[...]
debug1: Sending command: bash -c ls file-*
[...]
表示される他の3つのコマンドは同じように機能しますが、シェルなどではなく$0
文字列にのみ設定されます。file-*
$1
$2
bash -c
おそらくあなたが望むのは、完全なコマンドを引用することです。
ssh remote 'bash -c "ls file-*"'
ssh -v
デバッグ出力では、次のように報告されます。
[...]
debug1: Sending command: bash -c "ls file-*"
[...]
つまり、リモートコマンドに渡された文字列が引用符を削除した後、ローカルシェルで実行したいコマンドであることを確認する必要があります。
また、使用することができます
ssh remote bash -c \"ls file-\*\"
または
ssh remote bash -c '"ls file-*"'