両方のディレクトリからファイルのリストを取得し、違いを特定し、特定のファイルに対していくつかのコードを実行するスクリプトがあります。
以下は、ファイルのリストを取得するコマンドです。
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
最初comm
の引数の行のみを印刷するため、その行は両方の引数に表示されず、2番目の引数に一意に現れる行は印刷されません。
ただし、時にはエラーメッセージが表示されます。
command substitution: line 3: syntax error near unexpected token `('
command substitution: line 3: `comm -23 <(echo "$list_in") <(echo "$list_out")'
過去3週間で同じスクリプトが正しく機能していたので、これは私を本当に混乱させます。私はこれをクラスタで使用しているので、複数のプロセスが同時にスクリプトを実行できます。これでエラーが発生する可能性がありますか?
修正する。スクリプトはviaとして呼び出され、./script
明らかに以前に設定されましたchmod +x script
。
(免責事項:クラスタで作業していて、スクリプトの最初の3行にロック機構が含まれていない場合でも、ファイルは2回処理されません。)
ベストアンサー1
カーネルは、デフォルトで実行できる特定のファイル形式を認識します。これには、1 つ以上のバイナリ形式が含まれます。しかも#!
(シェルボーン)はスクリプトとして扱われます。たとえば、ファイルがにあり、/path/to/script
で始まる場合、呼び出し時にカーネルが実行されます#!/bin/bash
。/bin/bash /path/to/script arg1 arg2
/path/to/script arg1 arg2
カーネルがファイルの種類を認識しない場合、ファイルは ENOEXEC (Execution Format Error) を返します。execve
システムコール。 Shebang機能を持たないUnixカーネルの古代の伝統によれば、ほとんどのプログラムはENOEXECエラーで最初の試みが失敗したときにプログラムを再実行しようとします。つまり、/bin/sh
スクリプトインタプリタで実行しようとします。
Bashは注目すべき例外です。 BashはNETではなく独自にスクリプトを実行します/bin/sh
。したがって、Bashから呼び出すと、スクリプトが予期せず動作します。
shebang 行を省略すると、スクリプトを実行するプログラムによっては、スクリプトが/bin/bash
下または下で実行されることがあります。/bin/sh
そして/bin/sh
明らかに、システムのプロセス交換はサポートされていません。それでもbashになりますが(エラーメッセージはbashのエラーメッセージのように見えます)、名前でbashを呼び出すと、sh
プロセスオーバーライドをサポートしていないPOSIX互換モードになります。
物語の教訓は次のとおりです。 bashスクリプトを作成するには、#!/bin/bash
最初の行に配置する必要があります。