ls
は、再帰呼び出しをするときにファイルを正しくソートしないようです。
ls -altR . | head -n 3
ディレクトリ(サブディレクトリを含む)で最新のファイルを見つけるにはどうすればいいですか?
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のみのものであるように、stat -c
の使用法も同様です。 BSDでも同じことが可能ですが、フォーマットのオプションは異なります(-f "%m %N"
のようです)
そして私は複数形の部分を逃した。もっと最新のファイルが欲しいなら、単にtail引数を上げてください。
@ plundra's answer に続いて、BSDとOS Xのバージョンを示します。
find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "
結果をソートして最後に修正されたものだけを保存する代わりに、(unix時間で)修正時間が最も長いものだけを表示するためにawkを使うことができます。
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で動作します。
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
は最後に変更されたファイルのみを返しますこれはサブディレクトリでもうまくいくようです:
find . -type f | xargs ls -ltr | tail -n 1
ファイルが多すぎる場合は、検索を絞り込みます。
最新のファイルを人間が読める形式のタイムスタンプで表示します。
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
をより大きな番号に置き換えます。
これはソートされたリストを与えます:
find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5
Sortコマンドに '-r'を付けて順序を逆にしてください。ファイル名だけが必要な場合は、 "awk '{print $ 11}' |"を挿入してください。 'の前頭'
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 '%T@ %p\n' | sort -n -r | head -${numl} | cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}
それでも、ほとんどの作業はplundraの独自のソリューションによって行われました。ありがとうプルンドラ。
私は同じ問題に直面しました。最新のファイルを再帰的に見つける必要があります。見つけるには約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
ディレクトリの最新の変更項目を取得するのは再帰的関数です。この項目がディレクトリの場合、関数は再帰的に呼び出され、このディレクトリを検索します。
各ファイルでstat
を個別に実行するのが遅くなる場合は、xargs
を使用して処理を少し高速化できます。
find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" "
これはカレントディレクトリ内の全ディレクトリの変更時刻を各ディレクトリの最新ファイルに再帰的に変更します。
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
私はいつも似たようなものを使っているし、最近修正されたファイルのトップ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秒のソリューションを使用した場合のsortの7.5倍の高速化です。
この単純なcliでもうまくいきます。
ls -1t | head -1
あなたは-1をリストしたいファイルの数に変更することができます。
次のコマンドはSolaris上で機能しました。
find . -name "*Zip" -type f | xargs ls -ltr | tail -1
私は次のように短く、より解釈しやすい出力を見つけます。
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' '
最後の60分間に変更された/ target_directoryおよびそのすべてのサブディレクトリ内のファイルを検索するには:
$ find /target_directory -type f -mmin -60
更新時刻の逆順で並べ替えられた最新のファイルを見つけるには(つまり、最新の更新ファイルを最初に):
$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r
$ 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
リンクをたどります。
上記のコマンドが便利だと思いましたが、私の場合はファイルの日付と時刻を見る必要がありました。名前にスペースを含むいくつかのファイルで問題がありました。これが私の実用的な解決策です。
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l
私は同様に解決策が必要だったので、私はこの質問のために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>]
私はこれを好む、それは短いです:
find . -type f -print0|xargs -0 ls -drt|tail -n 1