深刻なアクセントを評価するときにbashの動作に問題があります。オプションの-nameを使用してfindを実行したいと思います。
find -name "*.log"
うまくいきますが、入れ子になったスクリプトから-name部分を取得したい場合
find `echo "-name \"*.log\""`
まったく動作しません。 bash -xで実行すると、コマンドが次のように評価されることがわかります。
find -name '"*.log"'
明らかに一重引用符のためだと思います。これを取り除くための回避策はありますか?ありがとうございます。
//要求されたオペレーティングシステムとbashバージョン:Debian、7.8 wheezy、Bash 4.2.37(1)-release
答え1
Bashはまだコマンドに一重引用符を追加しません。表示される単一引用符は、コマンドに有効なbash構文が表示されるように追加されました。見たら
find -name '"*.log"'
これは、bashがこのコマンドを実行するように指示されることを意味します:find
2つの引数-name
と"*.log"
(二重引用符は引数の一部です)。正確にこのように入力することも、他の同様の方法で入力することもできます。
find -name \"*.log\"
find -name "\"*.log\""
find -name '"*.'log""\"
今、あなたが書いた内容を見てみましょう。
find `echo "-name \"*.log\""`
サブシェルで実行するコマンドは次のとおりです。
echo "-name \"*.log\""
その出力は
-name "*.log"
ここでは、パラメータの二重引用符が生成されます。コマンド置換の出力がコマンドラインに挿入されると、シェル構文で解析されません。
find `echo '; rm -rf ~'`
すべてのファイルを削除するわけではありませんが、;
最初の引数find
、rm
2番目の引数、3番目の引数-rf
として渡し、ホームディレクトリ(特殊文字が含まれていないと仮定)を4番目の引数として渡します。
変数置換またはコマンド置換が二重引用符の外にある場合、変数値またはコマンド出力は次のように変換されます。
- コマンド置換のみ: 末尾の改行を削除します。
- 文字列はスペースで区切られたセグメントに分割されます。 (変数を設定して区切り文字を設定できます
IFS
。)この変換の結果は次のとおりです。リストひも。 - リストの各要素はワイルドカードパターンとして解釈されます。パターンがファイルと一致すると、その要素は一致するファイルのリストに置き換えられます。ワイルドカード)。パターンがファイルと一致しない場合、要素は保持されます。
ステップ2-name "*.log"
文字列を-name
との2つの部分に分割します"*.log"
。どちらの部分もファイルと一致しないため、結果は2つの単語-name
の合計です"*.log"
。
あなたが望むのは、find
パラメータを使用して-name
実行することです*.log
。ワイルドカードをオフにしてこれを行うことができます。
set -f
find `echo -name *.log`
set +f
これは強力ではありません。たとえば、スペースを含むファイル名を渡すことはできません。通常、コマンドのビットを変数に保存したり、コマンドに渡してコマンドを作成したりしないでください。現在やっていることを行う最善の方法は、実際にやりたいことが何であるかによって異なります。以下は、いくつかの一般的な提案です。
答え2
eval関数を使用すると問題が解決します。
command="find `echo \"-name \"*.log\"\"`" response=$(eval "$command")