ディレクトリで最新の変更されたファイルを再帰的に見つける方法は?


242

それはそうls再帰呼び出しを正しくソートファイルをやっていないとき:

ls -altR . | head -n 3

ディレクトリ(サブディレクトリを含む)で最近変更されたファイルを見つけるにはどうすればよいですか?


回答:


357
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "

巨大なツリーの場合、sortすべてをメモリに保持するのは難しいかもしれません。

%T@UNIXタイムスタンプのような変更時間を与え、sort -n数値でソートしtail -1、最後の行(最高のタイムスタンプ)を取りcut -f2 -d" "、最初のフィールド(タイムスタンプ)を出力から切り取ります。

編集:同じように-printf、おそらくのGNU-のみ、ajrealsの使用であるstat -cすぎです。BSDで同じことを行うことは可能ですが、フォーマットのオプションは異なります(-f "%m %N"それは思われるでしょう)

そして、私は複数形の部分を逃しました。あなたはもっとしたい場合は、最新のファイルを、ちょうど尾の引数をつり上げます。


7
順序が重要な場合は、のsort -rn | head -3代わりに使用を切り替えることができますsort -n | tail -3。1つのバージョンはファイルを最も古いものから最新のものに、もう1つのバージョンは新しいものから最も古いものに移動します。
Don Faulkner

3
巨大なディレクトリ(数万の小さなファイル)があり、パフォーマンスが心配でしたが、このコマンドは1秒未満で実行されました。ありがとうございます!!! :-)
lucaferrario 2013

2
「巨大な木では、すべてをメモリに保持しておくのは難しいかもしれません。」必要に応じてsort(で/tmp)一時ファイルを作成するので、それは問題ではないと思います。
Vladimir Panteleev 2014年

1
これを次の-printf '%T@ %Tb %Td %TY %p\n'ように変更すると、日付スタンプが表示されます(必要な場合)(と同様ls
bshea

1
私は以下のより短くて、より解釈可能な出力を見つけます:find . -type f -printf '%TF %TT %p\n' | sort | tail -1
snth

129

@plundraの回答に続き、BSDとOS Xのバージョンは次のとおりです。

find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "

1
代わりにBSD / OS Xをfindサポートしていますか?パイプなしで同じこと(複数のファイルをパラメーターとして渡す)を行うからです。+\;-print0 | xargs -0
DevSolar 2014

最後の5個またはn個のファイルを降順で変更したい場合はどうすればよいですか?
khunshan

変更@khunshan head -1head -5
エマーソンFarrugia

20

結果をソートして、最後に変更されたものだけを保持する代わりに、awkを使用して、(unix時間で)変更時間が最も長いものだけを出力することができます。

find . -type f -printf "%T@\0%p\0" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\0'

これは、ファイル数が十分に多い場合に問題を解決するためのより速い方法です。

理論的には、ファイル名には任意の文字(スペースや改行を含む)を含めることができるため、NUL文字(つまり「\ 0」)を使用しました。

システムにそのような病理的なファイル名がない場合は、改行文字も使用できます。

find . -type f -printf "%T@\n%p\n" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\n'

さらに、これはmawkでも機能します。


これは、最新の3つを維持するように簡単に調整できます。
追って通知があるまで一時停止。

1
これはmawk、Debian標準の代替であるで動作しません。
2014

いいえ、ただしその場合、気にならなければ改行文字を使用できます;)
marco

10

私はそこのSolaris 10の下の最後の修正されたファイルを見つけるためにトラブルがあっfindていないprintfオプションをしてstat使用できませんが。私にはうまくいく次の解決策を見つけました:

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1

ファイル名も表示するには、

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1

説明

  • find . -type f すべてのファイルを検索して一覧表示します
  • sed 's/.*/"&"/' 空白を処理するためにパス名を引用符で囲みます
  • xargs ls -E引用符付きのパスをに送信しますls。この-Eオプションにより、完全なタイムスタンプ(年-月-日時-分-秒-ナノ秒)が確実に返されます。
  • awk '{ print $6," ",$7 }' 日付と時刻のみを抽出します
  • awk '{ print $6," ",$7," ",$9 }' 日付、時刻、ファイル名を抽出します
  • sort 日付順にソートされたファイルを返します
  • tail -1 最後に変更されたファイルのみを返します

9

これは、サブディレクトリでも正常に機能するようです。

find . -type f | xargs ls -ltr | tail -n 1

ファイルが多すぎる場合は、検索を絞り込みます。


1
-lオプションは、ls不要と思われます。ちょうど-tr十分なようです。
Acumenus 2014

6
これはディレクトリごとにソートされるようですので、必ずしも最新のファイルが表示されるわけではありません
Fabian Schmengler

1
場合は、より良い行うファイルパスにスペースがありますfind . -type f -print0 | xargs -0 ls -ltr | tail -n 1
定期メンテナンス

最新のファイルが見つかりません。
K.-Michael Aye 2016年

1
ファイル名にスペースがある場合は、このブレークを考えて
waferthin

7

人間が読めるタイムスタンプで最新のファイルを表示します:

find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1

結果は次のようになります。

2015-10-06 11:30: +0200 ./foo/bar.txt

より多くのファイルを表示するに-n1は、より大きな番号に置き換えます


5

私はいつも似たようなものを使用していますが、最近変更されたファイルのトップkリストも使用しています。大きなディレクトリツリーの場合、並べ替えを回避する方はるかに高速です。最近変更されたファイルのトップ1の場合:

find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'

170万のファイルを含むディレクトリで、3.4秒で最新のファイルを取得します。これは、ソートを使用した25.5秒のソリューションに対して7.5倍のスピードアップです。


とてもかっこいい:eof()なら、最後の出力をsystem( "ls -l $ f")と交換して、日付もわかりやすく表示しました。
Martin T.

@MartinT。:すばらしい。どういたしまして。O(n)メソッドが利用可能な場合、人々が物事(O(n log n))をソートする本能を持っているのは不思議です。これは、ソートを回避する唯一の答えのようです。ところで、私が提案したコマンドの目標は、最新のファイルのパスを見つけることです。あなたは(たとえば、としてあなたのシェルでコマンドをエイリアスができlastfile)、その後、次のような結果に好きなあなた、行うことができls -l $(lastfile .)、またはopen $(lastfile .)(Macの場合)、など
ピエールD

ああ、私は正直に立っています。以下に別の回答があります(@marco)。+1。
Pierre D

4

これはソートされたリストを提供します:

find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5

sortコマンドに「-r」を配置して、順序を逆にします。ファイル名だけが必要な場合は、「awk '{print $ 11}' |」を挿入します '|の前 頭'


3

Ubuntu 13では、次のように実行します。並べ替えが逆になり、「末尾」ではなく「先頭」を使用するため、作業が軽減されます。ツリー内の最新の11個のファイルを表示するには:

見つける。-type f -printf '%T @%p \ n' | ソート-n -r | 頭-11 | カット-f2- -d "" | sed -e 's、^。/ ,,' | xargs ls -U -l

これにより、再ソートせずに完全なlsリストが得られ、「検索」がすべてのファイル名に付ける煩わしい「./」が省略されます。

または、bash関数として:

treecent () {
  local numl
  if [[ 0 -eq $# ]] ; then
    numl=11   # Or whatever default you want.
  else
    numl=$1
  fi
  find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} |  cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}

それでも、ほとんどの作業はplundraの元のソリューションによって行われました。ありがとうplundra。


3

私は同じ問題に直面しました。最新のファイルを再帰的に検索する必要があります。見つけるのに約50分かかりました。

これを速くするための小さなスクリプトは次のとおりです。

#!/bin/sh

CURRENT_DIR='.'

zob () {
    FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
    if [ ! -f ${FILE} ]; then
        CURRENT_DIR="${CURRENT_DIR}/${FILE}"
        zob
    fi
    echo $FILE
    exit
}
zob

これは、ディレクトリの最後に変更されたアイテムを取得する再帰的な関数です。このアイテムがディレクトリの場合、関数は再帰的に呼び出され、このディレクトリなどを検索します。


3

私は以下のより短くてより解釈可能な出力を見つけます:

find . -type f -printf '%TF %TT %p\n' | sort | tail -1

標準化されたISO形式の日時の固定長を考えると、辞書式ソートは問題なく-n、ソートのオプションは必要ありません。

タイムスタンプをもう一度削除したい場合は、次を使用できます。

find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '

2

stat各ファイルを個別に実行するxargsと速度が低下する場合は、少し高速化できます。

find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" " 

2

これにより、現在のディレクトリにあるすべてのディレクトリの変更時刻が、各ディレクトリの最新のファイルに再帰的に変更されます。

for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done

1
dirsにスペースが含まれていると、うまく動作しません。IFSを設定して引用符を使用する必要があります。IFS= $ '\ n'; for dir in $(find ./ -type d); 「$ dir」をエコーし​​ます。「$ dir」を検索-type f -printf '%T @ "%p" \ n' | ソート-n | 尾-1 | カット-f2- -d "" | xargs -I {} touch -r {} "$ dir"; 完了。
アンディリーロビンソン


1

上記のコマンドは役に立ちましたが、私の場合はファイルの日付と時刻を確認する必要があり、名前にスペースが含まれているいくつかのファイルで問題が発生しました。これが私の実用的な解決策です。

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l

1

次のコマンドはSolarisで機能しました。

find . -name "*zip" -type f | xargs ls -ltr | tail -1 

1

隠しファイルを無視—タイムスタンプが素晴らしく高速

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

結果

ファイル名のスペースを適切に処理します—これらを使用するべきではありません!

2017.01.25 18h23 Wed ./indenting/Shifting blocks visually.mht
2016.12.11 12h33 Sun ./tabs/Converting tabs to spaces.mht
2016.12.02 01h46 Fri ./advocacy/2016.Vim or Emacs - Which text editor do you prefer?.mht
2016.11.09 17h05 Wed ./Word count - Vim Tips Wiki.mht

もっと

findリンクをたどってより多くの


1

/ target_directoryおよびそのすべてのサブディレクトリで、過去60分間に変更されたファイルを検索するには、次のように入力します。

$ find /target_directory -type f -mmin -60

最近更新されたファイルを見つけるには、更新時間の逆順にソートします(つまり、最近更新されたファイルを最初に)。

$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r

0

私はこれが好きです、それはより短いです:

find . -type f -print0|xargs -0 ls -drt|tail -n 1

0

私も解決策が必要だったので、この質問のためにpypi / githubパッケージを作成しました。

https://github.com/bucknerns/logtail

インストール:

pip install logtail

使用法:変更されたファイルの末尾

logtail <log dir> [<glob match: default=*.log>]

使用法2:変更された最新のファイルをエディターで開く

editlatest <log dir> [<glob match: default=*.log>]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.