7

私は次のようなことをしたいです:

#!/bin/bash

cmd="find . -name '*.sh'"
echo $($cmd)

私が期待しているのは、現在のディレクトリにあるすべてのシェルスクリプトファイルが表示されることですが、何も起こりませんでした。

この投稿によると、evalで問題を解決できることを知っています

#!/bin/bash

cmd="find . -name '*.sh'"
eval $cmd

だから私の質問は、なぜここでコマンド置換が機能しないのか、そして質問に関して$(...)とevalの違いは何ですか?

4

3 に答える 3

1

コマンド置換はここで機能します。引用が間違っているだけです。あなたのスクリプトはファイル名を 1 つだけ見つけます! 一重引用符とアスタリスクが含まれているもの:

'*.sh'

このコマンドで通常とは異なるファイルを作成し、テストできます。

touch "'*.sh'"

bash での引用は、他のプログラミング言語とは異なります。この記事で詳細を確認してください: ホワイトシェル

あなたが必要とするのは、この引用です:

cmd="find . -name *.sh"
echo $($cmd)
于 2012-11-08T15:04:21.903 に答える
1

すでに*.sh二重引用符内にパターンが含まれているため、パターンを保護するために単一引用符を使用する必要はありません。その結果、単一引用符はパターンの一部になります。

*.shコマンド置換に渡されるまで、配列を使用して引用符を付けておくことができます。

cmd=(find . -name '*.sh')
echo $("${cmd[@]}")

パターンを展開せずに元の文字列を配列に変換する簡単な方法があるかどうかはわかりません。

更新: これはそれほど悪くはありませんが、可能であれば、配列を直接作成する方がよいでしょう。

cmd="find . -name *.sh"
set -f
cmd=($cmd)
set +f
echo $("${cmd[@]}")
于 2012-11-08T13:59:40.383 に答える
0

構文を使用する場合、echo $($cmd)基本的には、$cmd独自の行を配置することと同じです。問題は、コマンドを実行する前に bash がワイルドカードを補間する方法にあります。それを防ぐ方法*は、スクリプトでそれらを逆参照するときに、char を含む変数を再び引用符で囲むことです。

ただし、コマンド全体をfind . -name "*.sh"変数に入れ、それを `echo $("$cmd") で引用すると、シェルはその行全体が実行するファイルであると解釈し、ファイルが見つからないというエラーが発生します。 .

したがって、変数に本当に必要なものと、変数から何を引き出すことができるかによって異なります。変数にプログラムが必要な場合、これは機能します。

#!/bin/bash

cmd='/usr/bin/find'
$cmd . -name "*.sh" -maxdepth 1

.shこれにより、シェルがワイルドカードを補間せずに、現在の作業ディレクトリ内で終わるすべてのファイルが検索されます。

パターンを変数に入れる必要がある場合は、次を使用できます。

#!/bin/bash

pattern="*.sh"
/usr/bin/find . -name "$pattern" -maxdepth 1

しかし、すべてを変数に入れると、期待した結果が得られません。お役に立てれば。bash の第一人者が私が見逃していることを知っているなら、ぜひ聞きたいです。

于 2012-11-08T15:06:36.780 に答える