web-dev-qa-db-ja.com

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

lsは、再帰呼び出しをするときにファイルを正しくソートしないようです。

ls -altR . | head -n 3

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

223
JMW
find . -type f -printf '%[email protected] %p\n' | sort -n | tail -1 | cut -f2- -d" "

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

%[email protected]はunixタイムスタンプのような修正時間を与え、sort -nは数値順にソートし、tail -1は最後の行(最も高いタイムスタンプ)を取り、cut -f2 -d" "は出力から最初のフィールド(タイムスタンプ)を切り捨てます。

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

そして私は複数形の部分を逃した。もっと最新のファイルが欲しいなら、単にtail引数を上げてください。

333
plundra

@ plundra's answer に続いて、BSDとOS Xのバージョンを示します。

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

結果をソートして最後に修正されたものだけを保存する代わりに、(unix時間で)修正時間が最も長いものだけを表示するためにawkを使うことができます。

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

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

理論的には、ファイル名には任意の文字(スペースや改行を含む)が含まれる可能性があるため、NUL文字(つまり '\ 0')を使用しました。

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

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

また、これもmawkで動作します。

14
marco

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は最後に変更されたファイルのみを返します
10

これはサブディレクトリでもうまくいくようです:

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

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

9
mgratia

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

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をより大きな番号に置き換えます。

6

これはソートされたリストを与えます:

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

Sortコマンドに '-r'を付けて順序を逆にしてください。ファイル名だけが必要な場合は、 "awk '{print $ 11}' |"を挿入してください。 'の前頭'

4
Karlo

Ubuntu 13では、ソートが逆になり、 'tail'ではなく 'head'が使用され、作業量が減るため、次のようになります。 11個の最新のファイルをツリー表示するには:

find。-type f -printf '%T @%p\n' | sort -n -r | head -11 | cut -f2- -d "" | sed -e 's、^。/、 、 '| xargs ls -U -l

これは並べ替えをすることなく完全なlsリストを与え、 'find'がすべてのファイル名に付ける煩わしい './'を省略します。

あるいは、bash関数としては、

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

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

3
RickyS

私は同じ問題に直面しました。最新のファイルを再帰的に見つける必要があります。見つけるには約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
AnatomicJC

各ファイルでstatを個別に実行するのが遅くなる場合は、xargsを使用して処理を少し高速化できます。

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

これはカレントディレクトリ内の全ディレクトリの変更時刻を各ディレクトリの最新ファイルに再帰的に変更します。

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

私はいつも似たようなものを使っているし、最近修正されたファイルのトップkリストも使っている。大きなディレクトリツリーの場合は、ソートを回避する方がはるかに速いになります。最近変更されたファイルのトップ1だけの場合:

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

170万のファイルを含むディレクトリでは、3.4秒で最新のものが得られます。25.5秒のソリューションを使用した場合のsortの7.5倍の高速化です。

2
Pierre D

この単純なcliでもうまくいきます。

ls -1t | head -1

あなたは-1をリストしたいファイルの数に変更することができます。

2
Ankit Zalani

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

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

私は次のように短く、より解釈しやすい出力を見つけます。

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' '
1
snth

最後の60分間に変更された/ target_directoryおよびそのすべてのサブディレクトリ内のファイルを検索するには:

$ find /target_directory -type f -mmin -60

更新時刻の逆順で並べ替えられた最新のファイルを見つけるには(つまり、最新の更新ファイルを最初に):

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

隠しファイルを無視する - Nice&fastタイムスタンプ付き

$ 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

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

find . -type f -printf '%[email protected] %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
1
Roger Cable

私は同様に解決策が必要だったので、私はこの質問のために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>]
0
Nathan Buckner

私はこれを好む、それは短いです:

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