コマンドの実行とリダイレクトの順序

コマンドの実行とリダイレクトの順序

私が作成しているbashスクリプトの場合は、ディレクトリから最新の2つのファイルを除くすべてのファイルを削除する必要があります。

私はls -tUr > somefile.txt最新の2つを使用して追跡し、別の場所に移動してrm *から再度移動することにしました。

何らかの理由で実際にコマンドを使用するのが混乱している部分がsomefile.txt(ファイルの残りの部分に)表示されます。somefile.txttail

だから私の質問は、論理的にls現在のフォルダ/ファイルが返された後にリダイレクトされますが、明らかに実行する前に存在する必要があるsomefile.txtため、これは起こらないということです。somefile.txtls

答え1

これは、「なぜこれが起こるのか」という質問に対する答えです。

はい、実際にsomefile.txt実行する前に作成されます。ls

$ utility >file

最初に行われることは、シェルがリダイレクトを認識して作成file(またはすでに存在する場合は切り捨て)することです。それからutility標準出力ストリームは実行時に入りますfile

ユーティリティは通常、標準出力がどこに行くのか分からず、気にしません(たとえば、一部のユーティリティはlsTTYであることを確認し、それに応じて動作を変更します)。したがって、通常の出力ファイル、パイプに書き込むかどうかは重要ではありません。 、デバイスファイルまたはソケット。もちろん関係ありません。作るこのファイル。したがって、シェルの作業は、プロセスが開始される前にパイプが正しい位置にあることを確認することです。これには、file上記の例で指定されたファイルを作成または切り捨てる操作が含まれます。

最新のファイルを除くすべてのファイルを削除する質問に対する回答は、最も古いファイルの削除

答え2

Kusalanandaは既にsomefile.txt次の結果が出てきた理由についてあなたの質問に答えましたが、ls作られた最近解決されたリンクの問題でファイル修正済み代わりにファイル。

まず、出力をファイルに書き込む必要はありません。コマンドは互いに直接対話することができ、これはパイプの目的です。

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

ls -tU | tail -n +3 | xargs echo rm -f -- # echo for dry-run

tailただし、これは行と(引用可能な)単語で機能し、xargsファイル名が両方のいずれかであることを保証できないため、一般的なケースでは欠陥があります。有効なテキストであるという保証もありません。ファイル名に有効な文字を形成しない空白、改行、引用符、バックスラッシュ、またはバイトシーケンスが含まれていない場合にのみ正しく機能します。

システムがFreeBSDの場合(使用しているように)、次のように安定して解析できる出力形式を-U使用できます。json

ls --libxo=json -Ut |
  perl -MJSON::PP -l0 -0777 -ne '
    @files = map {$_->{name}} @{
      decode_json($_)->{"file-information"}->{directory}->[0]->{entry}
    };
    print for @files[2..$#files]' | xargs -0 echo rm -f --

関連情報