サブディレクトリを含む(大きな)ディレクトリで最新のファイル(mtime)を検索する場合、どうすればよいですか?
私が見つけた多くの投稿は、ls -lt | head
のいくつかのバリエーションを提案します(面白いことに、多くの人がls -ltr | tail
を提案しますが、これは同じですが効率は劣ります)。
それからまた、できます
find . -type f -exec ls -lt \{\} \+ | head
1つのコマンドで指定できる限り多くのファイルに対してトリックを確実に行います。つまり、bigディレクトリがある場合、-exec...\+
は個別のコマンドを発行します。したがって、各グループはグループ内でls
でソートされますが、合計セットではソートされません。したがって、ヘッドは最初のバッチの最後のエントリを取得します。
答えはありますか?
ls
は-printf
アクションを介して必要なことをすべて実行できるため、外部コマンド(find
として)を繰り返す必要はありません。
find /path -printf '%T+ %p\n' | sort -r | head
今日も同様の問題がありましたが、find
なしで攻撃しました。ホームディレクトリで最後に編集したファイルを返すために、ssh
を実行できる短いものが必要でした。これは私が思いついたものです。
ls -tp | grep -v /$ | head -1
ls
の-p
オプションはディレクトリに末尾のスラッシュを追加し、grep -v
はスラッシュで終わる行(別名、すべてのディレクトリ)を削除し、head -1
は出力を制限します単一のファイル。
ファイル名だけを返す場合は、find
を使用するよりもはるかに冗長です。
これは私のシステムではprintf
より高速ですが、理由はわかりませんが
find /path -type f -exec stat -c "%y %n" {} + | sort -r | head
編集:この投稿は、私が思ったほど「特に有用ではない」とは思いません。これは、ファイルのリスト全体をソートするのではなく、最後に変更されたファイルを追跡するだけの非常に高速なソリューションです。
find . -type f -printf '%T@ %p\n' | awk 'BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; } { if ($1 > mostrecenttime) { mostrecenttime = $1; mostrecentline = $0; } } END { print mostrecentline; }' | cut -f2- -d ' '
わかりやすくするために複数の行に展開します。次のようになります。
find . -type f -printf '%T@ %p\n' | awk '
BEGIN { mostrecenttime = 0; mostrecentline = "nothing"; }
{
if ($1 > mostrecenttime)
{ mostrecenttime = $1; mostrecentline = $0; }
}
END { print mostrecentline; }' | cut -f2- -d ' '
編集の終わり
特に有用な投稿ではありませんが、「アレンジ」が速度について議論しているので、これを共有すると思いました。
arrangeおよびEnzotibのソリューションでは、ディレクトリ内のすべてのファイルをmtimesでリストしてからソートします。ご存じのとおり、最大値を見つけるためにソートは必要ありません。最大値の検索は線形時間で実行できますが、ソートにはn log(n)時間かかります[違いはそれほど多くないが、それでも;)]。これをうまく実装する方法は考えられません。 [編集:きれいな(ただし汚い見た目)で高速な実装が上記で提供されています。
次善策-ディレクトリ内で最後に編集されたファイルを見つけるには、各レベル1サブディレクトリで最後に編集されたファイルを再帰的に見つけます。このファイルがサブディレクトリを表すようにします。次に、レベル1のサブディレクトリの代表とともにレベル1のファイルを並べ替えます。各ディレクトリのレベル1ファイルとサブディレクトリの数がほぼ一定の場合、このプロセスはファイルの総数に比例してスケーリングする必要があります。
これは私がこれを実装するために思いついたものです:
findrecent() { { find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1; }
findrecent .
これを実行すると、find: findrecent: No such file or directory
エラーが大量に発生しました。理由:findの-execが別のシェルで実行されます。 .bashrc、.xsessionrcでfindrecentを定義しようとしましたが、これらは助けにはなりませんでした[ここに助けていただければ幸いです]。最後に私はパッティングに頼った
#!/bin/bash
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;
pATHのfindrecent
というスクリプトで実行します。
私はこれを実行し、何も出力せずに待ち続けました。ただ、無限ループを処理していないことを確認するために、ファイルを
#!/bin/bash
echo "$1" >&2
{ find "$1" -maxdepth 1 -type f -exec stat -c "%y %n" {} + | sort -r | head -1 && find "$1" -mindepth 1 -maxdepth 1 -type d -exec findrecent {} \;; } | sort -r | head -1;
そして再試行しました。それはうまくいきましたが、私のホームフォルダで1分35秒かかりました-Arrangeとenzotibのソリューションはそれぞれ1.69、1.95秒かかりました!
O(n)のO(n log(n))に対する優位性はこれだけです!くそー関数呼び出しのオーバーヘッド! [むしろ、スクリプト呼び出しのオーバーヘッド]
しかし、このスクリプトは以前のソリューションよりも優れた拡張性を備えており、Googleのメモリバンクで実行するよりも速く実行されるに違いありません; D
それほどファッショナブルではありませんが、Midnight Commander:*を検索し、結果をパネル化して、変更時刻を逆順に並べ替えることでこれを実現することもできます。
明らかに、それはfind
より少し遅いです-922000ファイルを含む私のホームディレクトリは、mc
で5分未満しか使用されませんでしたが、ほぼ14分でfind
でソートされました。
私はおそらく、適切な検索呼び出しを発明するための9分の差よりも長い時間を費やすでしょう。
エラーの可能性が低い(ソートなどに-rを指定するのを忘れた-もう一度開始)
ソート順などを変更することで結果セットを再生することができます-ファイルを再クエリすることなく。
結果セットからsomeファイルに対してのみファイル操作を実行できます-つまり、サイズでソートし、不要ないくつかの大きなファイルを削除します
Perl
とともにconjonctinでfind
を使用します。
find my_directory -type f -printf '%T@\t%p\n' | Perl -ane '@m=@F if ($F[0]>$m[0]); END{print $m[1];}'
最もエポック==が最後に変更されたファイルの名前を取得します。