bash スクリプトで複雑なコマンドを実行する

bash スクリプトで複雑なコマンドを実行する

bash スクリプト内で次のコマンドを実行しようとしています:

rm -rf `ls -t ${FOLDER}/other_folder | awk 'NR>5'`

そして私は次のようなことを試しています:

RM_CMD="$(rm -rf 'ls -t ${FOLDER}/other_folder | awk NR>5')"

これは後で、コマンドを実際に実行する関数で使用されます。

いくつかのバリエーションを試しましたが、常に失敗します。ここでの正しいアプローチは何ですか?

-編集-

さらに詳しい情報

次のようなことを試してみたら

RM_CMD="rm -rf `ls -t ${FOLDER}/other_folder | awk 'NR>5'`"

コマンドをすぐに実行しようとしているようですが、これは意図したことではありません (後で実行するために正しいコマンドを保存したい)。ただし、正しい値はすべて取得され、空の値はありません。

-編集2-

次のように、コマンドを可能な限り分割してみました。

LS_CMD="ls -t ${FOLDER}/other_folder"    
AWK_CMD="awk 'NR>5' ${LS_CMD}"    
RM_CMD="rm -rf '${AWK_CMD}'"

しかし、次のような問題が発生します:

+ ssh -t user@server 'rm -rf '\''awk '\''NR>5'\'' ls -t /full/path/to/folder/other_folder'\'''
bash: 5 ls -t /full/path/to/folder/other_folder: No such file or directory

答え1

通常、このような質問に対する答えは、BashFAQ #50: 「変数にコマンドを入れようとしていますが、複雑なケースでは常に失敗します。」要約: 変数は実行可能なコードではなくデータ用であり、そこにコードを入れようとするとさまざまな問題が発生します。

しかし、この場合、もう1つの重要な要素があります。コマンドを 経由で実行するsshので、リモートシステムに渡されることになります。データとして、リモート コンピュータ上のシェルによってコマンドとして解析されます。つまり、コマンド (データとして) をスクリプト (ローカル コンピュータ上) の変数に格納するのが適切です。

私にとって、あなたが抱えている最大の問題は、バッククォートまたは$( )(シングルクォートではない)を使用すると、内部のコマンドが(ローカル コンピューター上で)即座に実行され、その出力が変数に格納されることのようです。これを回避するには、変数を定義するときに、関連する文字をエスケープします。

RM_CMD="rm -rf \$(ls -t '${FOLDER}/other_folder' | awk 'NR>5')"

一般的に好まれるため、私は$( )バッククォートの代わりに を使用していることに注意してください。バッククォートとシングルクォートを混同している箇所があるようです。これらは似ていますが、効果はまったく異なります。 は$( )基本的に同じことを行いますが、視覚的に曖昧ではありません。

${FOLDER}また、はローカル コンピュータ上の変数であると想定しているため、すぐに展開する必要があります (スペースやその他のシェル メタ文字が含まれている場合に備えて、一重引用符で囲んでいます)。リモート シェルによって展開される場合は、\"\${FOLDER|/other_folder\"代わりに を使用します。実際には、一重引用符自体が含まれている場合は、一重引用符で囲んで${FOLDER}も機能しません。これを修正する方法はありますが、ここでは気にしていません。

変数の割り当てにシングル クォートを使用することもできますが、その場合、コマンド内のシングル クォートで問題が発生しますawk(シングル クォートで囲まれた文字列内にシングル クォートをネストするクリーンな方法はありません)。また、ローカル コンピューター上で展開するクリーンな方法もありません${FOLDER}。これらは混合引用符で解決できますが、面倒です。

最後に、変数を使用するときは、二重引用符で囲む必要があります。

ssh -t user@server "$RM_CMD"

... この特定のケースでは問題にはなりませんが、二重引用符で囲まれていない変数参照ではさまざまな問題が発生する可能性があるため、通常は二重引用符で囲むことをお勧めします。

答え2

bashスクリプトの一般的なエラーは次のように確認できます。シェルチェックオンラインで機能しますが、オフラインプログラムさまざまなシェル (shebang で識別) をサポートし、スタイルに関する警告も表示します (この場合、$(...)バックティックの代わりに を使用します)。貼り付けたコードをライブ編集して、評価方法を確認することもできます (コーディング スタイルに関する通常のチュートリアルと組み合わせると便利です)。

関連情報