2つのディレクトリのファイルのリストを取得し、違いを取得して、特定のファイルに対していくつかのコードを実行することになっているスクリプトがあります。
ファイルリストを取得するためのコマンドは次のとおりです。
list_in=$(find input/ -maxdepth 1 - type f | sed 's/input\///' | sort -u);
list_out=$(find output/ -maxdepth 1 - type f | sed 's/output\///' | sort -u);
正しいディレクトリでスクリプトを実行するので、これは失敗しないはずです。未処理のファイルはによって決定されます
list_todo=$(comm -23 <(echo "$list_in") <(echo "$list_out"));
オプション-23
for comm
は最初の引数の行のみを出力するため、両方の引数に表示されず、2番目の引数に一意に表示される行も出力されません。
ただし、たまにしかエラーが発生します
command substitution: line 3: syntax error near unexpected token `('
command substitution: line 3: `comm -23 <(echo "$list_in") <(echo "$list_out")'
まったく同じスクリプトが過去3週間うまく機能したので、これは本当に私を困惑させます。これをクラスターで使用しているため、複数のプロセスがスクリプトを同時に実行する可能性があります。これが原因でエラーが発生する可能性がありますか?
更新。スクリプトは./script
で呼び出され、私は明らかに以前にchmod +x script
を設定しました。
(免責事項:クラスターで作業していて、スクリプトの最初の3行にロックメカニズムが含まれていない場合でも、もちろん、ファイルが2回処理されることはありません)
カーネルは、ネイティブに実行できる特定のファイル形式を認識します。これには、少なくとも1つのバイナリ形式が含まれます。さらに、#!
( Shebang )で始まるファイルはスクリプトと見なされます。たとえば、ファイルが/path/to/script
にあり、#!/bin/bash
で始まる場合、カーネルは/bin/bash /path/to/script arg1 arg2
を呼び出すと/path/to/script arg1 arg2
を実行します。
カーネルがファイル形式を認識しない場合、 execve
システムコールからENOEXEC(exec形式エラー)を返します。 Shebang機能を備えていなかったUnixカーネルの古代からの伝統に従い、ほとんどのプログラムは、最初の試行がエラーENOEXECで失敗したときに、プログラムの実行を2回試行します。/bin/sh
をスクリプトインタプリタ。
Bashは注目すべき例外です。スクリプトは、/bin/sh
ではなく、それ自体で実行されます。したがって、bashからスクリプトを呼び出したときに、スクリプトが誤って機能していました。
Shebang行を省略した場合、スクリプトは、実行元のプログラムに応じて、/bin/bash
または/bin/sh
で実行される可能性があります。そして、/bin/sh
は明らかにあなたのシステムでのプロセス置換をサポートしていません。おそらくまだbashです(エラーメッセージはbashからのもののように見えます)が、bashがsh
という名前で呼び出されると、プロセス置換をサポートしないPOSIX互換モードになります。
話の教訓:bashスクリプトを作成する場合は、最初の行に#!/bin/bash
を配置する必要があります。
$()および<()構文はbashのみです。つまり、シバンラインは次のようにする必要があります。
#!/bin/bash
特にこれはnot動作します:
#!/bin/sh
sh
で動作する必要がある場合は、$()の代わりに `を使用できます。
list_in=`find input/ -maxdepth 1 - type f | sed 's/input\///' | sort -u`
<()の代わりにmkfifoを使用できます。