次のスクリプトがあるとしましょう。
#!/bin/bash
printf '%q\n' "b c"
スクリプト印刷の実行:
b\ c
コマンドラインから。
次に、名前付きファイルを含むディレクトリからb c
スクリプトの出力を次のコマンドにパイプしたいと思いますls
。
$ ls $(./myscript)
ここでの問題はsum、つまり2つのパラメータb c
に分割されており、もちろんそのパラメータが見つからないことです。この問題を回避する方法はありますか?出力から空間を脱出するだけで十分だと思います。b\
c
ls
答え1
引用符を使用する:
$ ls "$(./myscript)"
答え2
コマンドの置き換え
コマンドの出力を他のコマンドの引数として渡す必要がある場合は、次のようにします。コマンドの置き換え。変数置換の場合と同様に、コマンド置換の結果は、単語分割($IFS
デフォルトではすべての文字からスペースに分割)とワイルドカード拡張(ファイル名のワイルドカード文字)を経ます。だから、コマンドの置き換えには常に二重引用符を使用してください。分割とワイルドカードが発生したくない場合。
ls -- "$(./myscript)"
--
ls
スクリプトで終わるファイル名を印刷する場合は、処理を停止するようにオプションに指示します-
。
テキストファイル名を印刷する必要があります。スクリプトに追加の参照を追加しないでください。
実際に引数がめちゃくちゃになることがある極端な場合があります。コマンド置換は、コマンド出力から最後の改行を削除します。したがって、出力がfoo↲bar
(foo↲bar↲
改行を表すために使用される)かどうかに関係なく、コマンドの引数はです。ファイル名には改行が許可されていますが、誰もそれを使用しないため、実際にこれはほとんど発生しません。ただし、システムをハッキングしたい人がファイル名に改行を入れることができるため、これはセキュリティ上のリスクになる可能性があります。foo↲bar↲↲↲
↲
ls
foo↲bar
最後の改行文字を処理するには、改行ではなく追加の文字を出力するようにコマンドをスケジュールし、コマンド置換の結果からそれらを削除します。
output=$(./myscript; echo a)
output="${output%a}"
ls -- "$output"
複数のファイル名をコマンドに渡す
ファイル名またはコマンドライン引数に表示できない文字の1つはNULLバイトです。コマンドに渡す複数のファイル名やその他の引数を出力する安全な方法は、それをヌルバイトで区切ってを呼び出すことですxargs -0
。これは、Linux、* BSD、およびOSXで動作しますが、他のUNIXバリアントには不足している可能性があるPOSIX拡張です。 。結果のコマンドラインが長すぎると、xargsはそれを分割してコマンドを複数回呼び出します。
… | xargs -0 ls
それ以外の場合は、-0
他のxargs
一般的なコマンドでは生成できない入力形式が必要です。入力にスペースなどが含まれていない場合\"'
。
入力を引用する1つの方法xargs
は、少なくとも改行、タブ、スペース、および文字の前にバックスラッシュを配置することです\"'
。
for x in …; do
printf '%s\n' "$x" | sed -e 's/[ '\''\"]/\\&/g' -e 's/$/\\$/' -e '$ s/\\$//'
done | xargs ls
角かっこ内の2つのスペース文字の代わりに、sedコマンドにスペースとタブ文字を入力します。
保護されていない置換と参照の追加の説明
保護されていない変数またはコマンド置換では、\[*?
ワイルドカードが表示される各単語に対して4文字が拡張されます。ただし、キャラクターだけあります。[*?
トリガーワイルドカード:他のワイルドカードのないバックスラッシュは変更されずにそのまま残ります。したがって、現在のディレクトリに、、、foo
というgoo
3つのファイルが含まれている場合は、bar
次のようになります。
ls $(echo '?oo bar')
ls
パラメータを使用して呼び出されますfoo
。goo
bar
ls $(echo '?\oo b\ar')
ls
パラメータを使用して呼び出されますfoo
。goo
b\ar