シェルで一時ファイルを使用する前に一時ファイルをクリーンアップできますか?

シェルで一時ファイルを使用する前に一時ファイルをクリーンアップできますか?

私のプログラムがクラッシュした場合、一時ファイルを避けたいと思います。

UNIXの驚くべきことは、ファイルを削除した後でもファイルを開いたままにできることです。

だからファイルを開いたら、時々削除してくださいそれから処理速度が遅い場合、プログラムがクラッシュしても、ユーザーがファイルをクリーンアップする必要がない可能性があります。

シェルでは、私はしばしば次のようなものを見る:

generate-the-file -o the-file
[...loads of other stuff that may use stdout or not...]
do_slow_processing < the-file
rm the-file

ただし、プログラムがクラッシュした場合、rmユーザーはクラッシュする前にプログラムをクリーンアップする必要がありますthe-file

Perlでは、次のことができます。

open(my $filehandle, "<", "the-file") || die;
unlink("the-file");
while(<$filehandle>) {
  # Do slow processing stuff here
  print;
}
close $filehandle;

これにより、ファイルが開くとすぐに削除されます。

シェルにも同様の構造がありますか?

答え1

これはcsh、tcsh、sh、ksh、zsh、bash、ash、sashでテストされました。

echo foo > the-file
(rm the-file; cat) < the-file | do_slow_processing
do_other_stuff

または必要に応じて:

(rm the-file; do_slow_processing) < the-file
do_other_stuff

興味深いことに、fifoでも動作します。

mkfifo the-fifo
(rm the-fifo; cat) < the-fifo | do_slow_processing &
echo foo > the-fifo

コンテンツが作成されるまでリーダーがブロックされるからです。

答え2

generate-the-file > the-file
exec 5< the-file
rm the-file
...
do_slow_processing 0<&5

メモ:

  • 実行可能ファイルなしでexecを実行する必要があるため、シェル自体の記述子に影響します。
  • 最大9つのfdのみが提供されます。
  • ファイル名が必要な場合は、/proc/self/fd/X を使用できます。このインタフェースはUNIXバージョン間で移植可能ではありません(あなたに適している可能性があります)。
  • fdを再読み込みしようとする試み(2回呼び出すなどcat 0<&5)はEOFにあるため失敗します。巻き戻しまたは読んで克服する必要があります。/proc/self/fd/X
  • 上記のほとんどの場合、実際のファイルがなくても実行できますが、簡単な操作も実行できます。generate-the-file | do_slow_processing

修正する:

OPでは、generate-the-file出力は標準出力として生成されない可能性があると述べました。これにはいくつかの慣用語があります。

  • 出力ファイルを指定します-。通常、出力ファイル名(stdoutを意味)を受け入れます。これはPOSIX.1-2017によって承認されました:

    ガイドライン13: 読み取りまたは書き込みのために列ファイルを表すためにオペランドを使用するユーティリティの場合、「-」オペランドは標準入力(または出力ファイルが指定されていることがコンテキストで明確である場合は標準出力)を表すためにのみ使用する必要があります。 )またはファイル名は-です。

generate-the-file(明確に定義されたユーティリティ以外のユーティリティの場合、実装によって定義されますが、ツールがそれをサポートする可能性が高いです。)

これはすべてのシェルで機能するわけではなく、オペレーティングシステムがfdファイル名をサポートする必要があります。

答え3

bashシェルでクリーンアップを処理する方法は、trap組み込みのEXIT(bashシェルに入力help trap)を使用することです。

trap 'rm temp-file' EXIT

dashこの機能はシェルにも存在し、sh最新のLinuxディストリビューションではエイリアシングとも呼ばれます。

関連情報