Temukan file terbaru berdasarkan tanggal yang dimodifikasi

39

Jika saya ingin menemukan file terbaru (mtime) dalam direktori (besar) yang berisi subdirektori, bagaimana saya melakukannya?

Banyak posting yang saya temukan menyarankan beberapa variasi ls -lt | head(mengejutkan, banyak yang menyarankan ls -ltr | tailyang sama tetapi kurang efisien) yang baik-baik saja kecuali Anda memiliki subdirektori (saya punya).

Kemudian lagi, Anda bisa

find . -type f -exec ls -lt \{\} \+ | head

yang pasti akan melakukan trik untuk file sebanyak yang dapat ditentukan oleh satu perintah, yaitu jika Anda memiliki direktori besar , -exec...\+akan mengeluarkan perintah terpisah; oleh karena itu masing-masing kelompok akan disortir dengan lssendirinya tetapi tidak lebih dari total yang ditetapkan; Oleh karena itu kepala akan mengambil entri terbaru dari batch pertama.

Ada jawaban?

Kaya
sumber
btw, kamu tidak perlu semua backslash itu.
enzotib
@enzotib: Anda ( \ + ), kalau tidak Anda dapatkanfind: missing argument to '-exec'
atur
@ mengatur: Saya tidak memiliki kesalahan ini, karena +tidak ada artinya bash, jadi tidak perlu menghindarinya.
enzotib
@enzotib: Anda benar, kesalahan saya, maaf
atur

Jawaban:

46

Anda tidak perlu berulang ke perintah eksternal (as ls) karena finddapat melakukan semua yang Anda butuhkan melalui -printftindakan:

find /path -printf '%T+ %p\n' | sort -r | head
enzotib
sumber
1
Ya, saya datang dengan find . -type f -exec stat --format=%y \{\} \+ | sort -r | head -n1tetapi solusi Anda jauh lebih bersih!
Rich
3
Tambahkan | cut -d ' ' -f2untuk mendapatkan nama file saja
qwr
Anda juga dapat memilah output headuntuk menyertakan sejumlah baris. Saya hanya perlu baris pertama, jadi saya menggunakanhead -n 1
Timmah
8

Saya memiliki masalah yang sama hari ini, tetapi saya menyerang tanpa itu find. Saya memerlukan sesuatu yang singkat yang dapat saya jalankan sshuntuk mengembalikan file yang baru diedit di direktori home saya. Inilah kira-kira yang saya pikirkan:

ls -tp | grep -v /$ | head -1

The -ppilihan untuk lsmenambahkan slash trailing untuk direktori, yang grep -vMenghapus garis berakhir di garis miring (alias, semua direktori), dan head -1batas-batas output ke file tunggal.

Ini jauh lebih tidak jelas daripada menggunakan findjika semua yang Anda ingin kembali adalah nama file.

Pat Regan
sumber
Ini tidak menangani subdirektori.
Clément
4

Ini pada sistem saya lebih cepat daripada printf, meskipun saya tidak mengerti mengapa

find /path -type f -exec stat -c "%y %n" {} + | sort -r | head
mengatur
sumber
Saya konfirmasi, lebih cepat.
enzotib
Satu hal lagi, ... | sort -r | head -n1 | cut -d " " -f 4-jika Anda ingin mendapatkan nama file saja.
林果 皞
Saya baru saja menemukan sort -rakan salah jika nama file di beberapa baris ada.
林果 皞
2

EDIT: Saya kira posting ini tidak 'tidak terlalu berguna' seperti yang saya kira. Ini adalah solusi yang sangat cepat yang hanya melacak file yang paling baru dimodifikasi (daripada menyortir seluruh daftar file):

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

Sebarkan beberapa baris untuk kejelasan seperti berikut:

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

Akhir dari EDIT


Bukan pos yang sangat berguna tetapi karena 'mengatur' membahas kecepatan, saya pikir saya akan membagikan ini.

solusi mengatur dan enzotib melibatkan daftar semua file di dalam direktori dengan waktu mereka dan kemudian menyortir. Seperti yang Anda ketahui penyortiran tidak perlu untuk menemukan yang maksimal. Menemukan maksimum dapat dilakukan dalam waktu linier tetapi pengurutan membutuhkan waktu n log (n) [Saya tahu perbedaannya tidak banyak, tetapi tetap;)]. Saya tidak bisa memikirkan cara yang rapi untuk mengimplementasikan ini. [EDIT: A rapi (meskipun terlihat kotor) dan implementasi cepat disediakan di atas.]

Hal terbaik berikutnya - Untuk menemukan file yang paling baru diedit dalam direktori, secara rekursif cari file yang paling baru diedit di setiap subdirektori level 1. Biarkan file ini mewakili subdirektori. Sekarang urutkan file level 1 bersama dengan perwakilan dari subdirektori level 1. Jika jumlah jumlah file level 1 dan sub-dir dari masing-masing direktori hampir konstan, maka proses ini harus skala secara linear dengan jumlah total file.

Inilah yang saya buat untuk mengimplementasikan ini:

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 .

Saya menjalankan ini dan mendapat banyak find: findrecent: No such file or directorykesalahan. Alasan: -exec dari find running di shell yang berbeda. Saya mencoba mendefinisikan findrecent di .bashrc, .xsessionrc tetapi ini tidak membantu [Saya akan menghargai bantuan di sini]. Pada akhirnya saya memilih untuk meletakkan

#!/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;

dalam skrip bernama findrecentPATH saya dan kemudian jalankan.

Saya menjalankan ini, terus menunggu dan menunggu tanpa hasil. Hanya untuk memastikan saya tidak berurusan dengan loop tak terbatas, saya memodifikasi file

#!/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;

dan mencoba lagi. Itu berhasil - tetapi butuh 1 menit 35 detik pada homefolder saya - solusi mengatur dan enzotib mengambil masing-masing 1,69, 1,95 detik!

Begitu banyak keunggulan O (n) dibanding O (n log (n))! Sialan kau fungsi panggilan overhead! [Atau lebih tepatnya panggilan skrip panggilan]

Tapi skrip ini memiliki skala yang lebih baik daripada solusi sebelumnya dan saya yakin itu akan berjalan lebih cepat daripada mereka di bank memori google; D

S Prasanth
sumber
2

Gunakan perldalam conjonctin dengan find:

 find my_directory -type f -printf '%T@\t%p\n' | perl -ane '@m=@F if ($F[0]>$m[0]); END{print $m[1];}'

Anda mendapatkan nama file dengan zaman terbesar == file terakhir yang dimodifikasi.

MUY Belgia
sumber
1

Ini hampir tidak modis, tetapi juga mungkin untuk mencapai ini dengan Midnight Commander : cari *, panelisasi hasilnya, urutkan berdasarkan waktu modifikasi dalam urutan terbalik.

Jelas, ini sedikit lebih lambat dari find- direktori home saya, yang berisi 922000 file, disortir mcdalam hampir 14 menit sementara findmenghabiskan kurang dari 5 - tetapi ada beberapa manfaat:

  • Saya mungkin akan menghabiskan waktu lebih lama daripada perbedaan 9 menit untuk menemukan doa permohonan yang tepat :)

  • lebih sedikit kemungkinan kesalahan (lupa menentukan -r untuk mengurutkan dll. - mulai lagi)

  • dimungkinkan untuk bermain dengan hasil yang ditetapkan dengan mengubah urutan urut dll - tanpa meminta kembali file.

  • mungkin untuk melakukan operasi file hanya pada beberapa file dari set hasil - yaitu mengurutkan berdasarkan ukuran, menghapus beberapa file besar yang tidak diperlukan

Sergey
sumber