5

後で何かをする必要がある bash スクリプトを作成しました。これは次のように呼ばれます。

later mv *.log /somewhere/else

しかし、このよう*.logに呼び出すと、呼び出し時に展開され、スクリプトが呼び出されたかのように記述されます

later mv 1.log 2.log 3.log /somewhere/else

スクリプトでワイルドカードを後で展開しようとしています。こんな風に呼んでみた

later mv '*.log' /somewhere/else

と も使用\*できますが、これらはどちらもワイルドカードがまったく展開されない結果になります。

コマンドラインでワイルドカードを展開するにはどうすればよいですか? また、スクリプトが呼び出されたときに拡張を防ぐ方法はありますか。つまり、入力された元のパラメーターを取得する方法はありますか?

これは、後で呼び出しを準備するスクリプトの一部です。

tmpfile=$(mktemp)

### Get a quoted commandline
line=
while (( "$#" > 0 )); do
        line="$line\"$1\" "
        shift
done

### Prepare a script to be run
echo '#!/bin/bash' > "$tmpfile"
echo "cd $(pwd)" >> "$tmpfile"
echo "trap 'rm \"$tmpfile\"' EXIT" >> "$tmpfile"
echo "$line" >> "$tmpfile"
chmod 777 "$tmpfile"

一部のファイルとフォルダーの名前にスペースが含まれているため、コマンドラインを引用する必要があることに注意してください。引用ビットを削除すると、ワイルドカードのないビットでも機能しなくなります。

4

3 に答える 3

5

興味深い質問です。私よりも良い答えが可能だと思います。それにもかかわらず、与えられた

A='foo.*'

これはあなたが望むことをするようです:

echo $(eval echo "$A")
于 2012-08-03T00:34:38.903 に答える
1

最も簡単な方法は、展開のためにワイルドカード (グロブ) をシェルに戻すことです。

例えば:

 #!/bin/bash
 echo "For the wildcard $1"
 echo "I find these match(es): $(eval echo "$1")"

オペレーターは$( … )サブシェルを呼び出し、結果を補間します。echoコマンドは単にそれらを返します。

  • @thb が回答に入れているようにeval、シェル スクリプト内では必要です (ただし、インタラクティブ シェルでキー入力する場合は必要ありません。この場合$(echo $1)は機能します。

スペースなどをエスケープする必要があることに注意してください。ただし、それを考慮しているようです。当然、スクリプトを呼び出すときにグロブを引用符で囲む必要があります。これが、ほとんどの Unix コマンドが最初または最後の位置で 1 つのリストしかとらない理由findです。

PS: シェルに強制的に展開を実行させないプログラムについては: いいえ、そうする組み込みの方法はありません。シェルは、プログラムが存在するファイルを特定する前に (必ずしも時系列でなくても、論理的には「前に」) グロブを展開し、どのプログラムを実行するかについてはかなり普遍的に認識しません。

于 2012-08-03T00:29:50.937 に答える