Linuxのディレクトリで最新のファイルを取得する


181

ディレクトリ内の最新の単一のファイルを返すコマンドを探します。

制限パラメータが表示されませんls...


1
watch -n1 'ls -Art | tail -n 1'-最後のファイルを表示します

ここでのほとんどの回答は、出力を解析するlsか、使用findせず-print0に迷惑なファイル名を処理するのに問題があります。常に言及しておくと便利です:この問題に対するPOSIXの回答を提供する
BashFAQ099

回答:


264
ls -Art | tail -n 1

エレガントではありませんが、機能します。


2
ls -Artlsを使用すると、ファイルの日付も表示できます。
Josir 2014

13
軽微な問題:このバージョンはlstoのすべての出力をパイプ処理しtail、最後の行のみを出力します。私見ではheadchaos推奨されているように、昇順でソートして代わりに使用することをお勧めします。最初の行のヘッドの印刷が終了すると、次の行(実際には次のブロック)を送信するとSIGPIPEが発生し、ls同様に終了します。
TrueY

1
@TrueY私はかなり同意します。カオスの答えは、効率性のために優れています。
dmckee ---元モデレーターの子猫2014

2
このソリューションには、ファイルだけでなくディレクトリも含まれることに注意してください。これは良いことにも悪いことにもなり得ます。それは個々のユーザーが何を望んでいるかによります。私がこれを取り上げた理由は、元の質問が「ファイル」と言っているためです。
Sildoreth 2015年

2
頭の代わりに尾を使用することの意図された利点は、lsによって返される合計を表す行を含めることを除外することであると私は思う。
ピータースコット

155
ls -t | head -n1

このコマンドは、実際には現在の作業ディレクトリにある変更された最新のファイルを提供します。


私のものと同等で、おそらくもっと効率的です。
dmckee ---元モデレーターの子猫09/06/18

最初にlsのいくつかの情報をエコー出力するので、私にとってはうまくいきませんが、使用方法を取得していただき、ありがとうございます!
ACK

4
@Josirこれを変更して、で日付スタンプを含めることができます。これは、ls -tl | head -n 1私のようにパイプ全体をテーブル全体にプッシュする必要はありません。
dmckee ---元モデレーターの子猫2014

1
@noɥʇʎԀʎzɐɹƆ– 2017ls -t *.png | head -n1
混乱

4
これは、最後に変更されたものである場合にフォルダーを返しls -Art | head -n1ます。特に、最後に変更されたファイルが必要な場合
achasinh

79

これは再帰的なバージョンです(つまり、特定のディレクトリまたはそのサブディレクトリのいずれかで最近更新されたファイルを見つけます)

find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1

編集:使用-f 2-の代わりに、-f 2ケビンにより示唆されるように


5
ここでは、Mac用のソリューションがあります:find $DIR -type f -exec stat -lt "%Y-%m-%d" {} \+ | cut -d' ' -f6- | sort -n | tail -1
ユーザー

2
問題は、カットコマンドが-f 2の代わりにスペースを含むパスを切り捨て、フィールド2を行末に戻すために-f2-を使用することです
Kevin

2
カオスによる提案のように、を使用して並べ替えを逆にすると、代わりにをsort -nr使用して効率をわずかに向上させることができます。(ただし、再帰的検索をソートする場合、最初または最後の行を取得することは遅い部分ではありません。)head -n 1tail -n 1
destenson

2
非常に便利!でもlsにパイプするともっとフレンドリーだと思います:find ./ -type f -printf "%T@ %p\n" -ls | sort -n | cut -d' ' -f 2- | tail -n 1 | xargs -r ls -lah
Simon

@userのMacバージョンは、日付ではなく日付のみをソート/表示します。これが修正バージョンです:find $DIR -type f -exec stat -lt "%F %T" {} \+ | cut -d' ' -f6- | sort -n | tail -1
yoz

11

信頼性に関する注意:

改行文字はファイル名と同様に有効であるため、/ ベースのなどの行に依存するソリューションには問題があります。headtail

GNU lsでは、もう1つのオプションは、--quoting-style=shell-alwaysオプションとbash配列を使用することです。

eval "files=($(ls -t --quoting-style=shell-always))"
((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

(隠しファイルも考慮したい場合は、-Aオプションを追加してlsください)。

通常のファイル(ディレクトリ、fifos、デバイス、シンボリックリンク、ソケットなどは無視)に制限したい場合は、GNUに頼る必要がありますfind

bash 4.4以降(の場合readarray -d)およびGNU coreutils 8.25以降(の場合cut -z):

readarray -t -d '' files < <(
  LC_ALL=C find . -maxdepth 1 -type f ! -name '.*' -printf '%T@/%f\0' |
  sort -rzn | cut -zd/ -f2)

((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

または再帰的に:

readarray -t -d '' files < <(
  LC_ALL=C find . -name . -o -name '.*' -prune -o -type f -printf '%T@%p\0' |
  sort -rzn | cut -zd/ -f2-)

ここでの最善の方法はzshbashこの面倒な作業をすべて回避する代わりに、そのglob修飾子を使用することです。

現在のディレクトリにある最新の通常ファイル:

printf '%s\n' *(.om[1])

非表示のものを含む:

printf '%s\n' *(D.om[1])

2番目に新しい:

printf '%s\n' *(.om[2])

symlink解決後にファイルの経過時間を確認します。

printf '%s\n' *(-.om[1])

再帰的に:

printf '%s\n' **/*(.om[1])

また、補完システム(compinitおよびco)を有効にCtrl+Xmすると、最新のファイルに展開する補完機能になります。

そう:

vi Ctrl+Xm

最新のファイルを編集します(を押す前に、それを確認することもできますReturn)。

vi Alt+2Ctrl+Xm

2番目に新しいファイル。

vi * .cCtrl+Xm

最新のcファイル。

vi *(。)Ctrl+Xm

最新の通常のファイル(ディレクトリやfifo / device ...ではない)など。


zshヒントをありがとう。これに関する詳細へのリンクをzsh docsに提供できますか?
9:31に凍結

@freezed、参照info zsh qualifiers
Stephane Chazelas

おかげで@Stephane Chazelas
凍結

9

私が使う:

ls -ABrt1 --group-directories-first | tail -n1

フォルダーを除いて、ファイル名だけが表示されます。


ディレクトリにディレクトリしかない場合を除き
ealfonso 2013年

8

ls -lAtr | tail -1

他のソリューションには、で始まるファイルは含まれていません'.'

このコマンドには'.'and も含まれます'..'。これは、必要な場合とそうでない場合があります。

ls -latr | tail -1


これは "。"を返しますか?含まれているどのファイルよりも最近にディレクトリが変更された場合(たとえば、削除によって)?多分それは望ましい振る舞いであろうし、そうでないかもしれない。しかし、あなたはどちらの方法でも正しい。
dmckee ---元モデレーターの子猫09/06/18


5

私はecho *(om[1])zsh構文)が好き です。ファイル名を指定するだけで、他のコマンドは呼び出されません。


1
zshを使用している場合は問題なく動作します。zshを使用していませんか?Ubuntuではbashがデフォルトだと思います。zshをインストールするか、bashと同等のコマンドを見つけることができます。
MikeB 2014

3
コマンドは「エコー」です。パラメータを評価して標準出力に送信するだけです。この場合、グロブ修飾子「om [1]」には「o」が付きます。これは、一致するファイルを「m」で順序付けすることを意味します。これは変更された時間です。そして、その順序付けられたリストから、最初のファイルである[1]を取ります。グロブ修飾子について読むことができます:zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers
MikeB

4

検索/並べ替えソリューションは、ファイル数が(ファイルシステム全体のように)本当に大きくなるまで、うまく機能します。代わりにawkを使用して、最新のファイルを追跡します。

find $DIR -type f -printf "%T@ %p\n" | 
awk '
BEGIN { recent = 0; file = "" }
{
if ($1 > recent)
   {
   recent = $1;
   file = $0;
   }
}
END { print file; }' |
sed 's/^[0-9]*\.[0-9]* //'

3

個人的には、組み込みでないbashコマンドをできる限り少なく使用することを好みます(高価なforkおよびexec syscallの数を減らすため)。日付でソートするには、ls呼び出す必要があります。しかし、の使用headは本当に必要ではありません。次のワンライナーを使用しています(名前パイプをサポートするシステムでのみ機能します)。

read newest < <(ls -t *.log)

または最も古いファイルの名前を取得する

read oldest < <(ls -rt *.log)

(2つの '<'マークの間のスペースに注意してください!)

隠しファイルも必要な場合-argを追加できます。

これがお役に立てば幸いです。


ファイル名が$ oldest / newest varに格納されていることを説明する必要があります。ただし、フォークの数が少ない場合は+1。
squareatom 2015年

@squareatomは組み込みをかなりよく知っていると思いました。しかし、あなたは正しい、多分違う。コメントありがとうございます!
TrueY

3
組み込みが何であるかを知っているとすれば、あなたは正解です。しかし、私はただOPの質問について考えていました。彼らは何かを返すコマンドを求めました。技術的には、ソリューションは何も出力しません。したがって、「&& echo $ newest」または同様の末尾に追加するだけです;-)
squareatom

3

R再帰オプションの使用..これは、ここで良い答えの拡張機能と見なすことができます

ls -arRtlh | tail -50

2
ls -t -1 | sed '1q'

フォルダ内の最後に変更されたアイテムを表示します。とペアリングしgrepて、キーワードを持つ最新のエントリを検索します

ls -t -1 | grep foo | sed '1q'

「1q」とは何ですか?1最初の行head -n 1はqと同じですか?
HattrickNZ 2016年

2

再帰的に:

find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

1

この簡単なコマンドを試してください

ls -ltq  <path>  | head -n 1

ファイル名が必要な場合-最終変更、パス= /ab/cd/*.log

ディレクトリ名が必要な場合-最終変更、パス= / ab / cd / * /



1

唯一バッシュビルトイン、密接以下とBashFAQ / 003

shopt -s nullglob

for f in * .*; do
    [[ -d $f ]] && continue
    [[ $f -nt $latest ]] && latest=$f
done

printf '%s\n' "$latest"

0

これらのls / tailソリューションはすべてサブディレクトリを無視してディレクトリ内のファイルに対して完全に正常に動作します。

すべてのファイルを(再帰的に)検索に含めるには、findを使用できます。gioeleさんは、フォーマットされた検索出力をソートすることを提案しました。ただし、空白には注意してください(この提案は空白では機能しません)。

これはすべてのファイル名で機能するはずです。

find $DIR -type f -printf "%T@ %p\n" | sort -n | sed -r 's/^[0-9.]+\s+//' | tail -n 1 | xargs -I{} ls -l "{}"

これはmtimeでソートされます。manfindを参照してください。

%Ak    File's  last  access  time in the format specified by k, which is either `@' or a directive for the C `strftime' function.  The possible values for k are listed below; some of them might not be available on all systems, due to differences in `strftime' between systems.
       @      seconds since Jan. 1, 1970, 00:00 GMT, with fractional part.
%Ck    File's last status change time in the format specified by k, which is the same as for %A.
%Tk    File's last modification time in the format specified by k, which is the same as for %A.

で置き換え%T%C、ctimeでソートします。


@gioele提案の空白の問題については正しいですが、-fオプションにハイフンを追加するだけで、それを修正できる範囲にすることができます。 find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1 または、最初のフィールドを除いてすべて保持: find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 1 --complement | tail -n 1
Aaron

0

パターンに従ってすべてのディレクトリで最新のファイルを検索します。たとえば、名前が「tmp」で終わる作業ディレクトリのサブディレクトリ(大文字と小文字は区別されません):

find . -iname \*tmp -type d -exec sh -c "ls -lArt {} | tail -n 1" \;

0
ls -Frt | grep "[^/]$" | tail -n 1

1
OPの質問を提供する他の回答があり、それらは何年も前に投稿されました。回答を投稿するときは、特に古い質問に回答する場合は、新しいソリューションまたは大幅に優れた説明を追加してください。
help-info.de

2
@ help-info.deコードのみの回答の削除には投票しないでください。それらは素晴らしいものではない
Machavity

@Machavity-私は失敗しないことを望み、遅い回答に対してのみコメントをしました。
help-info.de

0

サブディレクトリも含めて最新の変更ファイルを取得したい場合は、この小さなワンライナーでそれを行うことができます:

find . -type f -exec stat -c '%Y %n' {} \; | sort -nr | awk -v var="1" 'NR==1,NR==var {print $0}' | while read t f; do d=$(date -d @$t "+%b %d %T %Y"); echo "$d -- $f"; done

変更されたファイルではなく同じことをしたいが、アクセスされたファイルに対しては、単純に変更する必要があります

statコマンドから%Xへの%Yパラメータ。そして、最近アクセスしたファイルに対するコマンドは次のようになります。

find . -type f -exec stat -c '%X %n' {} \; | sort -nr | awk -v var="1" 'NR==1,NR==var {print $0}' | while read t f; do d=$(date -d @$t "+%b %d %T %Y"); echo "$d -- $f"; done

両方のコマンドで、1つ以上のファイルを一覧表示する場合は、var = "1"パラメータを変更することもできます。


-1

私もそれをする必要があり、これらのコマンドを見つけました。これらは私のために働きます:

フォルダ(アクセス時間)内の作成日で最後のファイルが必要な場合:

ls -Aru | tail -n 1  

そして、内容が変更された最後のファイルが必要な場合(時間を変更):

ls -Art | tail -n 1  
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.