Unix / Linux menemukan dan mengurutkan berdasarkan tanggal yang dimodifikasi

138

Bagaimana saya bisa melakukan yang sederhana findyang akan memesan hasil dengan paling baru dimodifikasi?

Berikut ini adalah saat ini findsaya menggunakan (saya melakukan shell escape di PHP, jadi itulah alasan untuk variabel):

find '$dir' -name '$str'\* -print | head -10

Bagaimana saya bisa memesan pesanan ini dengan yang paling baru dimodifikasi? (Catatan Saya tidak ingin ini untuk mengurutkan 'setelah' pencarian, tetapi mencari hasil berdasarkan apa yang baru-baru ini dimodifikasi.)

Peter Mortensen
sumber
github.com/shadkam/recentmost akan melakukan apa yang diinginkan - tetapi orang perlu membangunnya
user3392225

Jawaban:

153

Gunakan ini:

find . -printf "%T@ %Tc %p\n" | sort -n

printfargumen dari man find:

  • %Tk: Waktu modifikasi terakhir file dalam format yang ditentukan oleh k.

  • @: detik sejak 1 Januari 1970, 00:00 GMT, dengan bagian pecahan.

  • c: tanggal dan waktu lokal (Sab 04 12:02:33 EST 1989).

  • %p: Nama file.

pengguna195696
sumber
5
+1 Sangat berguna, jawaban pertama untuk ini saya temukan dengan keluaran tanggal yang dapat dibaca / berguna
Jake N
paling dapat diandalkan (dan sangat sederhana) karena waktu diberikan secara numerik berurutan (karenanya selalu dapat diurutkan dengan benar), thx!
Aquarius Power
1
Saya memiliki alias ini untuk menemukan file terbaru di saya ~/.zshrc: fr () { find ./ -iname "*"$@"*" -printf "%T@ %Td-%Tb-%TY %Tk:%TM %p\n" | sort -n | cut -d " " -f 2- | grep -i "$@" ; }Secara rekursif menemukan semua file yang berisi pola argumen pertama diteruskan ke perintah ( fr <pattern>) dan mengurutkannya dengan yang terbaru terakhir.
joelostblom
Ini bagus !!! Untuk menggunakan dengan symlink, gunakanfind -L ...
Varun Chandak
1
Anda mungkin ingin menggunakan sseduntuk menyingkirkan bagian pecahan detik dan masih menggunakan ISO8601 seperti yang ditunjukkan @PeterMortensen:find . -type f -printf "%TY-%Tm-%TdT%TT %p\n" | sort -r | ssed -R 's/^([^.]+)\.\d+ (.*)$/\1 \2/'
Ludovic Kuty
83

Metode termudah adalah menggunakan zsh, terima kasih kepada kualifikasi globalnya .

print -lr -- $dir/**/$str*(om[1,10])

Jika Anda menemukan GNU, buatlah untuk mencetak waktu modifikasi file dan urutkan berdasarkan itu.

find -type f -printf '%T@ %p\0' |
sort -zk 1nr |
sed -z 's/^[^ ]* //' | tr '\0' '\n' | head -n 10

Jika Anda memiliki GNU yang menemukan tetapi bukan utilitas GNU lainnya, gunakan baris baru sebagai pemisah, bukan nol; Anda akan kehilangan dukungan untuk nama file yang mengandung baris baru.

find -type f -printf '%T@ %p\n' |
sort -k 1nr |
sed 's/^[^ ]* //' | head -n 10

Jika Anda memiliki Perl (di sini saya akan menganggap tidak ada baris baru dalam nama file):

find . -type f -print |
perl -l -ne '
    $_{$_} = -M;  # store file age (mtime - now)
    END {
        $,="\n";
        @sorted = sort {$_{$a} <=> $_{$b}} keys %_;  # sort by increasing age
        print @sorted[0..9];
    }'

Jika Anda memiliki Python (dengan asumsi tidak ada baris baru dalam nama file):

find . -type f -print |
python -c 'import os, sys; times = {}
for f in sys.stdin.readlines(): f = f[0:-1]; times[f] = os.stat(f).st_mtime
for f in (sorted(times.iterkeys(), key=lambda f:times[f], reverse=True))[:10]: print f'

Mungkin ada cara untuk melakukan hal yang sama di PHP, tapi saya tidak tahu.

Jika Anda ingin bekerja hanya dengan alat POSIX, itu agak lebih rumit; lihat Cara membuat daftar file yang diurutkan berdasarkan tanggal modifikasi secara rekursif (tidak ada perintah stat tersedia!) (memulai kembali 10 yang pertama adalah bagian yang mudah).

Gilles
sumber
Saya pikir findversi menunjukkan file tertua, dan Anda perlu menambahkan -ropsi sort.
Quentin Pradet
Sed saya mengatakan itu tidak memiliki opsi -z.
Kef Schecter
@KefSchecter Kemudian gunakan baris baru sebagai pemisah, tetapi Anda akan kehilangan dukungan untuk baris baru dalam nama file.
Gilles
Di atas adalah untuk python2. Jika Anda hanya memiliki python3, beberapa perubahan kecil: python3 -c 'import os, sys; times = {} untuk f di sys.stdin.readlines (): f = f [0: -1]; times [f] = os.stat (f) .st_mtime untuk f in (diurutkan (times.keys (), key = lambda f: times [f], reverse = True)) [: 10]: print (f); '
Neil McGill
40

Anda tidak perlu PHP atau Python, cukup ls :

man ls:
-t     sort by modification time
-r,    reverse order while sorting (--reverse )
-1     list one file per line

find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;

Jika perintah * keluar dengan status kegagalan (mis. Daftar argumen terlalu panjang ), maka Anda dapat beralih dengan find. Diparafrasekan dari: Panjang maksimum argumen untuk proses baru

  • find . -print0|xargs -0 command (mengoptimalkan kecepatan, jika find tidak mengimplementasikan "-exec +" tetapi tahu "-print0")
  • find . -print|xargs command (jika tidak ada spasi di argumen)

Jika bagian utama dari argumen terdiri dari jalur panjang, absolut atau relatif, maka cobalah untuk memindahkan tindakan Anda ke direktori: cd /directory/with/long/path; command *Dan perbaikan cepat lainnya mungkin untuk mencocokkan lebih sedikit argumen:command [a-e]*; command [f-m]*; ...

Ярослав Рахматуллин
sumber
1
Jika ada banyak file, ini gagal dengan 'Daftar argumen terlalu panjang' di ls.
occulus
1
Itu benar, tetapi saya yakin pertanyaannya adalah "bagaimana cara saya menemukan ..."
Ярослав Рахматуллин
2
ls tidak mengutip nama file dengan cara yang dimengerti xargs (tidak ada opsi -0, dan berbagai gaya penawaran tidak memadai)
Tobu
10

Anda hanya perlu ls

Anda dapat melakukan find /wherever/your/files/hide -type f -exec ls -1rt "{}" +;seperti yang disebutkan di atas,

atau

ls -1rt `find /wherever/your/file/hides -type f`
skippy1910
sumber
2
Jika ada banyak file, ini gagal dengan 'Daftar argumen terlalu panjang' di ls. Mungkin recook untuk menggunakan xargs?
occulus
2
Tetapi jika xargspanggilan lsbeberapa kali, jenisnya akan rusak.
Aaron D. Marasco
Ini gagal untuk file dengan spasi di namanya. Ada saran?
user74094
Baru saja menemukan jawaban ini dan itulah yang saya butuhkan dalam situasi yang sama. Pertanyaan: apa yang dilakukan +;pada akhirnya? Tampaknya memberikan hasil yang sama tanpa ;tetapi tidak berfungsi tanpa +?
RocketNuts
Ini sama dengan jawaban lain yang diposting 8 bulan sebelumnya, kecuali untuk bagian tentang menggunakan "ls -1rt` find ... `", yang rusak
Clément
7

Memperluas jawaban user195696 :

find . -type f -printf "%T@\t%Tc %6k KiB %p\n" | sort -n | cut -f 2-

Untuk setiap file, ini output pertama timestamp numerik (untuk menyortir oleh, diikuti oleh tabulasi \t), maka timestamp terbaca-manusia, maka filesize (sayangnya find's -printftidak bisa melakukan di mebibyte, hanya kibibyte), maka nama file dengan relatif jalan.

Kemudian sort -nurutkan berdasarkan bidang angka pertama.

Lalu cutsingkirkan bidang angka pertama yang tidak menarik bagi pengguna. (Mencetak bidang kedua ke depan.) Pemisah bidang default adalah \tatau tabulasi.

Contoh output:

Thu 06 Feb 2014 04:49:14 PM EST     64 KiB ./057_h2_f7_10/h2_f7_10.class
Fri 07 Feb 2014 02:08:30 AM EST 7962976 KiB ./056_h2_f7_400/h2__rh_4e-4.mph
Fri 07 Feb 2014 02:23:24 AM EST 7962976 KiB ./056_h2_f7_400/h2_f7_400_out_Model.mph
Fri 07 Feb 2014 02:23:24 AM EST      0 KiB ./056_h2_f7_400/h2_f7_400_out.mph.status
Fri 07 Feb 2014 02:23:24 AM EST     64 KiB ./056_h2_f7_400/1579678.out
Fri 07 Feb 2014 03:47:31 AM EST 8132224 KiB ./057_h2_f7_10/h2__rh_1e-5.mph
Fri 07 Feb 2014 04:00:49 AM EST 8132224 KiB ./057_h2_f7_10/h2_f7_10_out_Model.mph
Fri 07 Feb 2014 04:00:49 AM EST      0 KiB ./057_h2_f7_10/h2_f7_10_out.mph.status
Fri 07 Feb 2014 04:00:49 AM EST     64 KiB ./057_h2_f7_10/1579679.out
Fri 07 Feb 2014 09:47:18 AM EST   9280 KiB ./056_h2_f7_400/h2__rh_4e-4.mat
Fri 07 Feb 2014 10:51:23 AM EST   9728 KiB ./018_bidomain/h2_plain__rh_1e-5.mat
Fri 07 Feb 2014 10:58:33 AM EST   9568 KiB ./057_h2_f7_10/h2__rh_1e-5.mat
Fri 07 Feb 2014 05:05:38 PM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.java
Fri 07 Feb 2014 06:06:29 PM EST     32 KiB ./058_h2_f7_stationary/slurm.slurm
Sat 08 Feb 2014 03:42:07 AM EST      0 KiB ./058_h2_f7_stationary/1581061.err
Sat 08 Feb 2014 03:42:14 AM EST     64 KiB ./058_h2_f7_stationary/h2_f7_stationary.class
Sat 08 Feb 2014 03:58:28 AM EST  70016 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mph
Sat 08 Feb 2014 04:12:40 AM EST  70304 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mph
Sat 08 Feb 2014 04:12:53 AM EST  70304 KiB ./058_h2_f7_stationary/h2_f7_stationary_out_Model.mph
Sat 08 Feb 2014 04:12:53 AM EST      0 KiB ./058_h2_f7_stationary/h2_f7_stationary_out.mph.status
Sat 08 Feb 2014 04:12:53 AM EST     32 KiB ./058_h2_f7_stationary/1581061.out
Mon 10 Feb 2014 11:40:54 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_4e-4.mat
Mon 10 Feb 2014 11:42:32 AM EST    224 KiB ./058_h2_f7_stationary/h2s__rh_1e-5.mat
Mon 10 Feb 2014 11:50:08 AM EST     32 KiB ./plot_grid.m

Saya sengaja membuat bidang filesize 6 karakter, karena jika membuatnya lebih lama, menjadi sulit untuk secara visual membedakan seberapa besar file tersebut. Dengan cara ini, file yang lebih besar dari 1e6 KiB menonjol: dengan 1 karakter berarti 1-9 GB, dengan 2 karakter berarti 10-99 GB, dll.


Sunting: ini versi lain (sejak find . -printf "%Tc"crash di MinGW / MSYS):

find . -type f -printf "%T@\t%p\n" | sort -n | cut -f 2- | xargs -I{} ls -Glath --si {}

Memberikan output seperti:

-rw-r--r-- 1 es 23K Jul 10  2010 ./laptop_0000071.jpg
-rw-r--r-- 1 es 43M Jul 29 19:19 ./work.xcf
-rw-r--r-- 1 es 87K Jul 29 20:11 ./patent_lamps/US Patent 274427 Maxim Lamp Holder.jpg
-rw-r--r-- 1 es 151K Jul 29 20:12 ./patent_lamps/Edison screw-in socket.png
-rw-r--r-- 1 es 50K Jul 29 20:13 ./patent_lamps/1157 Lamp.jpg
-rw-r--r-- 1 es 38K Jul 29 20:14 ./patent_lamps/US06919684-20050719-D00001.png

Dimana:

  • -I{}menyebabkan terjadinya {}digantikan oleh argumen, dan baris baru sekarang menjadi pemisah argumen (perhatikan spasi dalam nama file di atas).

  • ls -G menekan pencetakan nama grup (buang-buang ruang).

  • ls -h --simenghasilkan ukuran file yang dapat dibaca manusia (lebih tepat dengan --si).

  • ls -t mengurutkan berdasarkan waktu, yang tidak relevan di sini, tapi itulah yang biasanya saya gunakan.

Evgeni Sergeev
sumber
1
Catatan: untuk mengurutkan berdasarkan ukuran file , cukup ganti dengan T@dengan ssalah satu dari perintah di atas.
Evgeni Sergeev
3

Varian OS X dari jawaban @ user195696:

  1. Dengan cap waktu:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r
    
  2. Tanpa cap waktu:

    find . -type f -exec stat -f "%Sm %N" -t "%Y%y%m%d%H%M" {} \; | sort -r | awk -F' ' '{ print substr($0, length($1) + 2) }'
    
pengguna9399
sumber
2

Saya menemukan bahwa ini menyelesaikan pekerjaan di Mac OS X (dan cukup umum untuk bekerja pada Unixen lainnya):

find . -type f -ls | awk '{print $(NF-3), $(NF-2), $(NF-1), $NF}' | sort
Bryan Petty
sumber
2
Sayangnya, ini mencetak nama bulan yang dilokalkan pada pengaturan Kroasia saya, membuat semacam salah.
Ivan Vučica
jawaban user195696 berfungsi untuk pengaturan Kroasia (dan lainnya).
Peter Mortensen
1

Jika findpilihan Anda sangat sederhana, Anda mungkin dapat melakukannya tanpa itu, dan cukup gunakan ls:

ls -1 *.cc # -r -t optional
djc
sumber
1

Mencoba:

find '$dir' -name '$str'\* -print | xargs ls -tl | head -10

Tetapi juga berguna untuk memfilter data dengan -mmin/ -mtimedan -type.

Peter Mortensen
sumber
1

Menggunakan:

find . -type f -mtime 0 -printf "[%TD %TI:%TM%Tp] %s %p\n" | sort -n | awk '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';

Perintah ini akan mengurutkan file berdasarkan tanggal yang dimodifikasi.

Dan ditampilkan seperti:

[12/05/13 03:10PM] 1.75 MB ./file.text
[12/06/13 11:52PM] 2.90 MB ./file2.mp4
[12/07/13 04:11PM] 4.88 MB ./file3.mp4
[12/07/13 09:17PM] 4.74 MB ./test.apk
Akash
sumber
Saya ditingkatkan sript ini untuk menangani spasi dalam nama file, lihat superuser.com/a/777007/134532
Januari
1

Saya punya solusi sederhana yang berfungsi untuk FreeBSD (OS X) dan Linux:

find . -type f -exec ls -t {} +
Alex Shchur
sumber
Ini berfungsi dengan baik - seharusnya jawaban yang benar, atau setidaknya berperingkat lebih tinggi!
digitaltoast
0

Saya tidak berpikir findmemiliki opsi untuk memodifikasi pemesanan output. -mtimedan -mminakan membiarkan Anda membatasi hasil untuk file yang telah dimodifikasi dalam jendela waktu tertentu, tetapi hasilnya tidak akan diurutkan - Anda harus melakukannya sendiri. GNU findmemiliki -printfopsi yang, antara lain, akan memungkinkan Anda mencetak waktu modifikasi dari setiap file yang ditemukan (format string %tatau %Tk); yang mungkin membantu Anda mengurutkan findoutput seperti yang Anda inginkan.

Jim Lewis
sumber
0

Saya meningkatkan jawaban Akashs dengan membuat script yang menangani spasi putih dalam nama file dengan benar:

find . -type f -mtime 0 -printf ";[%TD %TI:%TM%Tp];%s;%p\n" | sort -n | awk -F ";" '{
    hum[1024**4]="TB"; hum[1024**3]="GB"; hum[1024**2]="MB"; hum[1024]="KB"; hum[0]="B";
    for (x=1024**4; x>=1024; x/=1024){
    if ($3>=x) { printf $1" "$2"\t%7.2f %s\t%s\n",$3/x,hum[x],$4;break }
    }}';
jan
sumber
0

Jika Anda ingin memesan semua file PNG berdasarkan waktu di $PWD:

Satu garis sederhana ini memberikan semua fleksibilitas regexp pada finddan di ls.

find $PWD -name "*.png" -print0 | xargs -0 ls -laht | less
John Smith
sumber
0

Anda dapat menggunakan statBSD dan Linux (bukan pada POSIX) dengan cara ini:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | cut -f2-

Jika Anda ingin membatasi jumlahnya:

$ stat -f "%m%t%N" /[the dir]/* | sort -rn | head -[the number] | cut -f2-
drewk
sumber
0

Ada cara sort | headtanggal yang bersih dan kuat :

Menggunakan ls -luntuk mencetak cantik

find . ! -type d -printf "%T@ %p\0" |
    sort -zrn |
    head -zn 10 |
    sed -z 's/^[0-9.]\+ //' |
    xargs -0 ls -lt

Sebagai fungsi :

findByDate() {
    local humansize=''
    [ "$1" = "-h" ] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p\0" |
        sort -zrn |
        head -zn ${1:--0} |
        sed -z 's/^[0-9.]\+ //' |
        xargs -0 ls -dlt${humansize}
}

Ini bisa dijalankan dengan satu atau dua argumen, atau bahkan tanpa:

Usage: findByDate [-h] [lines] [find options]

Sampel:

findByDate

Akan mencantumkan semua direktori non diurutkan berdasarkan tanggal. Tidak a:

Bahkan pada pohon sistem file besar, seperti xargs daftar yang sudah diurutkan, pesanan file tetap benar, bahkan jika lsharus dijalankan berkali-kali.

findByDate -h 12

Akan menampilkan 12 direktori terbaru bukan diurutkan berdasarkan tanggal, dengan ukuran dicetak dalam bentuk yang dapat dibaca manusia

findByDate 42 '-type l'

Akan mencantumkan 42 lebih banyak symlink terbaru

findByDate -0 '( -type l -o -type b -o -type s -o -type c )'

Akan mencantumkan semua symlink, perangkat blok, perangkat soket dan karakter, diurutkan berdasarkan tanggal.

Pesanan pembalikan

Mengganti headoleh taildan mengubah saklar dari sortdan ls:

findByDate() {
    local humansize=''
    [ "$1" = "-h" ] && humansize='h' && shift
    find . ${2:-! -type d} -printf "%T@ %p\0" |
        sort -zn |
        tail -zn ${1:-+0} |
        sed -z 's/^[0-9.]\+ //' |
        xargs -0 ls -dltr${humansize}
}

Fungsi yang sama, penggunaan yang sama:

Usage: findByDate [-h] [lines] [find options]
F. Hauri
sumber
-1

Jika Anda hanya ingin mendapatkan path lengkap dari setiap item, Anda dapat menulis seperti ini.

 find FIND_ROOT -maxdepth 1 -type f -printf "%T@ %p\n" | sort -nr | head -10 | cut -d ' ' -f 2

Di mana
-printf "% T @% p \ n" untuk memberikan kriteria penyortiran (tanggal),
'sort -nr' untuk menyortir menurut tanggal,
kepala -10 untuk daftar 10 hasil teratas,
cut -d '' -f 2 untuk memotong cap waktu terkemuka di setiap baris.

David Jung
sumber
cut -d ' ' -f 2akan rusak jika nama file mengandung spasi.
F. Hauri
-3

Saya punya solusi sederhana.

Setelah cdke direktori, gunakan

find . -iname "*" -ls

bernyanyi
sumber
1
Ini tidak mengurutkan berdasarkan tanggal yang dimodifikasi.
DavidPostill