私が作成しているbashスクリプトの場合は、ディレクトリから最新の2つのファイルを除くすべてのファイルを削除する必要があります。
私はls -tUr > somefile.txt
最新の2つを使用して追跡し、別の場所に移動してrm *
から再度移動することにしました。
何らかの理由で実際にコマンドを使用するのが混乱している部分がsomefile.txt
(ファイルの残りの部分に)表示されます。somefile.txt
tail
だから私の質問は、論理的にls
現在のフォルダ/ファイルが返された後にリダイレクトされますが、明らかに実行する前に存在する必要があるsomefile.txt
ため、これは起こらないということです。somefile.txt
ls
答え1
これは、「なぜこれが起こるのか」という質問に対する答えです。
はい、実際にsomefile.txt
実行する前に作成されます。ls
$ utility >file
最初に行われることは、シェルがリダイレクトを認識して作成file
(またはすでに存在する場合は切り捨て)することです。それからutility
標準出力ストリームは実行時に入りますfile
。
ユーティリティは通常、標準出力がどこに行くのか分からず、気にしません(たとえば、一部のユーティリティはls
TTYであることを確認し、それに応じて動作を変更します)。したがって、通常の出力ファイル、パイプに書き込むかどうかは重要ではありません。 、デバイスファイルまたはソケット。もちろん関係ありません。作るこのファイル。したがって、シェルの作業は、プロセスが開始される前にパイプが正しい位置にあることを確認することです。これには、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 --