私の端末でうまく機能するコード行があります:
for i in *.mp4; do echo ffmpeg -i "$i" "${i/.mp4/.mp3}"; done
次に、スクリプトにまったく同じコード行を挿入しますmyscript.sh
:
#!/bin/sh
for i in *.mp4; do echo ffmpeg -i "$i" "${i/.mp4/.mp3}"; done
ただし、実行するとエラーが発生します。
$ sh myscript.sh
myscript.sh: 2: myscript.sh: Bad substitution
他の質問に基づいて、シバンを#!/bin/bash
、しかし、まったく同じエラーが表示されます。このスクリプトを実行できないのはなぜですか?
TL; DR:bash
固有の機能を使用しているため、スクリプトはbash
ではなくsh
で実行する必要があります。
readlink -f $(which sh)
を使用します。Bash固有のスクリプトが常に正しく実行されるようにする最善の方法
ベストプラクティスはbothです:
$ sh myscript.sh myscript.sh: 2: myscript.sh: Bad substitution $ bash myscript.sh ffmpeg -i bar.mp4 bar.mp3 ffmpeg -i foo.mp4 foo.mp3
を#!/bin/sh
(またはスクリプトが依存する他のシェル)に置き換えます。#!/bin/bash
または./myscript.sh
を使用して、先頭のsh
またはbash
なしでこのスクリプト(およびその他すべて)を実行します。以下に例を示します。
/path/to/myscript.sh
(関連: なぜスクリプトの前に./がありますか? )
$ cat myscript.sh #!/bin/bash for i in *.mp4 do echo ffmpeg -i "$i" "${i/.mp4/.mp3}" done $ chmod +x myscript.sh # Ensure script is executable $ ./myscript.sh ffmpeg -i bar.mp4 bar.mp3 ffmpeg -i foo.mp4 foo.mp3
の意味シバンは、システムがスクリプトを実行するために使用するシェルを提案します。これにより、
#!/bin/sh
または#!/usr/bin/python
を指定できるため、どのスクリプトがどの言語で書かれているかを覚えておく必要がありません。移植性を最大限にするために、限られた機能セット(POSIX標準で定義)のみを使用する場合、人々は
#!/bin/bash
を使用します。#!/bin/sh
は、便利なbash拡張機能を利用するユーザースクリプトに最適です。
#!/bin/bash
は通常、最小限のPOSIX準拠シェルまたは標準シェル(bashなど)にシンボリックリンクされています。後者の場合でも、bash
が manpage で説明されている互換モードで実行されるため、/bin/sh
は失敗する可能性があります。Shという名前でbashが呼び出されると、POSIX標準にも準拠しながら、shの歴史的なバージョンの起動時の動作を可能な限り模倣しようとします。
#!/bin/sh
の意味Shebangは、
sh myscript.sh
、./myscript.sh
を実行するとき、または拡張機能をドロップして、スクリプトを/path/to/myscript.sh
のディレクトリに配置し、myscript
を実行するときにのみ使用されます。 。インタープリターを明示的に指定すると、そのインタープリターが使用されます。
$PATH
は、Shebangが何と言っても、sh
で強制的に実行します。これが、シバンの変更だけでは十分ではない理由です。常に優先インタープリターでスクリプトを実行する必要があります。そのため、スクリプトを実行するときは常に
sh myscript.sh
などを優先してください。スクリプトへの他の提案された変更:
./myscript.sh
の代わりに"$i"
)。保存されたファイル名に空白文字が含まれている場合、引用符で囲まれた変数は問題を防ぎます。$i
の代わりに"${i%.mp4}.mp3"
だけを使用するため、"${i/.mp4/.mp3}"
の代わりに${parameter%Word}
を使用することをお勧めします(たとえば、foo.mp4.backup
という名前のファイル)。${var/x/y/}
構文はPOSIXではありません。あなたの場合、変数の最後の文字列を削除して別の文字列を追加するだけの場合、ポータブルPOSIXソリューションは
#!/bin/sh
for i in *.mp4; do
ffmpeg -i "$i" "${i%.mp4}.mp3"
done
またはさらに短い、ffmpeg -i "$i" "${i%4}3"
。
これらの構造の決定的なドープは、 POSIXシェルのパラメーター拡張 の章です。