Cara daftar file yang diurutkan berdasarkan tanggal modifikasi secara rekursif (tidak ada perintah stat tersedia!)

31

Bagaimana saya bisa mendapatkan daftar semua file di bawah direktori saat ini bersama dengan tanggal modifikasinya dan diurutkan berdasarkan tanggal itu?

Sekarang saya tahu bagaimana mencapainya find, statdan sort, tetapi untuk beberapa alasan aneh statitu tidak diinstal pada kotak dan tidak mungkin saya bisa menginstalnya.

Ada pilihan lain?

PS: gcctidak diinstal juga

alex
sumber
Bisakah Anda mengunggah biner yang dikompilasi dan menjalankannya di sana?
imz - Ivan Zakharyaschev
@ imz: ya, itu cara lain. The find -printftindakan tampaknya meskipun termudah.
alex

Jawaban:

27

Metode terpendek saya menggunakan zsh:

print -rl -- **/*(.Om)

(tambahkan Dkualifikasi glob jika Anda juga ingin membuat daftar file tersembunyi atau file dalam direktori tersembunyi).

Jika Anda menemukan GNU, buatlah untuk mencetak waktu modifikasi file dan urutkan berdasarkan itu. Saya berasumsi tidak ada baris baru dalam nama file.

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

Jika Anda memiliki Perl (sekali lagi, dengan asumsi tidak ada baris baru dalam nama file):

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

Jika Anda memiliki Python (sekali lagi, 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]): print f'

Jika Anda memiliki akses SSH ke server itu, pasang direktori di atas sshfs pada mesin yang lebih baik:

mkdir mnt
sshfs server:/path/to/directory mnt
zsh -c 'cd mnt && print -rl **/*(.Om)'
fusermount -u mnt

Dengan hanya alat POSIX, ini jauh lebih rumit, karena tidak ada cara yang baik untuk menemukan waktu modifikasi file. Satu-satunya cara standar untuk mengambil waktu file adalah ls, dan format output tergantung lokal dan sulit untuk diurai.

Jika Anda dapat menulis ke file, dan Anda hanya peduli pada file biasa, dan tidak ada baris baru dalam nama file, inilah kludge yang mengerikan: buat tautan keras ke semua file dalam satu direktori, dan urutkan berdasarkan waktu modifikasi.

set -ef                       # disable globbing
IFS='
'                             # split $(foo) only at newlines
set -- $(find . -type f)      # set positional arguments to the file names
mkdir links.tmp
cd links.tmp
i=0 list=
for f; do                     # hard link the files to links.tmp/0, links.tmp/1, …
  ln "../$f" $i
  i=$(($i+1))
done
set +f
for f in $(ls -t [0-9]*); do  # for each file, in reverse mtime order:
  eval 'list="${'$i'}         # prepend the file name to $list
$list"'
done
printf %s "$list"             # print the output
rm -f [0-9]*                  # clean up
cd ..
rmdir links.tmp
Gilles 'SANGAT berhenti menjadi jahat'
sumber
Cara termudah mungkin find . -print | xargs -n99999 -s999999 ls -ltr. Tetapi itu memiliki masalah yang (1) xargsmungkin tidak memungkinkan -mlebih dari 512 atau -slebih besar dari 5120, dan (b) bahkan jika Anda dapat mengatasinya, masih ada ukuran maksimum yang dipaksakan oleh kernel dari daftar argumen dan lingkungan gabungan. Sebagian besar ide Anda (kecuali yang Perl dan Python) memiliki masalah yang sama, itulah sebabnya saya secara khusus menghindari membangun garis perintah yang panjang.
geekosaur
Secara khusus, saya secara teratur mendapatkan "daftar argumen terlalu lama" kesalahan menggunakan zshgumpalan rekursif dalam kasus umum.
geekosaur
@geekosaur: Hanya kludge mengerikan terakhir yang memiliki masalah dengan baris perintah panjang. Di zsh, Anda dapat melakukan banyak hal dengan built-in (mis print -rl **/*. Satu-satunya batasan adalah berapa banyak memori bebas yang Anda miliki), dan di luar itu ada zargs. Proposal Anda find … | xargs … lsakan disortir dengan benar jika hanya xargsmemohon lssekali saja, dan tidak akan berfungsi jika ada karakter khusus dalam nama file.
Gilles 'SO- berhenti bersikap jahat'
terima kasih banyak atas jawaban yang sangat terperinci dengan banyak pilihan! :)
alex
Dan itu sebabnya saya suka zsh.
Profpatsch
14

Dengan asumsi GNU find:

find . -printf '%T@ %c %p\n' | sort -k 1n,1 -k 7 | cut -d' ' -f2-

Ubah 1n,1ke 1nr,1jika Anda ingin file terdaftar paling baru terlebih dahulu.

Jika Anda tidak memiliki GNU, finditu menjadi lebih sulit karena lsformat stempel waktu sangat bervariasi (misalnya, file yang dimodifikasi memiliki stempel waktu yang berbeda, misalnya).

geekosaurus
sumber
Sebenarnya Anda juga dapat mengubah format tanggal dan waktu dengan ls --time-style="..."- Saya tidak yakin apakah ini standar atau GNU, sepertinya GNU.
asoundmove
GNU pasti.
geekosaur
@asoundmove: sayangnya, kotaknya terlalu tua (RedHat 7.2) dan lstidak memiliki opsi itu.
alex
7

Pada mac tidak ada argumen-printf untuk ditemukan, tetapi Anda dapat melakukan ini sebagai gantinya:

find . -print0 | xargs -0 -n 100 stat -f"%m %Sm %N" | sort -n|awk '{$1="";print}'

killdash9
sumber
0

seseorang dapat mencoba ini (kita harus membangunnya sendiri) https://github.com/shadkam/recentmost

pengguna3392225
sumber
6
Selamat datang di Unix & Linux Stack Exchange! Sementara ini secara teoritis dapat menjawab pertanyaan, akan lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
slm
0

Mengabaikan file tersembunyi - dengan cap waktu yang bagus & cepat

Menangani spasi dalam nama file dengan baik - bukan berarti Anda harus menggunakannya!

$ 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

Lebih findberlimpah dapat ditemukan dengan mengikuti link.

Serge Stroobandt
sumber
0

Berbicara secara umum tentang menemukan file berdasarkan tanggal (ini tidak akan berfungsi untuk poster asli, tapi saya berakhir di sini jadi saya pikir orang lain mungkin juga). Dalam kasus penggunaan saya, saya ingin membuat daftar file dengan tujuan meninjau mereka sebelum dihapus.

Dengan findutils 4.6.0 Saya suka:

find . -type f -mtime +270 -exec ls -laFGht --time-style=iso {} \+

Perintah di atas menemukan file ( -type f), dalam direktori kerja saat ini ( .) yang telah dimodifikasi lebih dari 270 hari yang lalu ( -mtime +270Juga -mtime 0akan menghasilkan 24 jam terakhir, dan -mtime -5menunjukkan 5 hari terakhir). Kemudian digunakan lsuntuk mendaftar mereka berdasarkan tanggal, terbaru terlebih dahulu ( -exec ls -laFGht --time-style=iso {} \+)

Berikut contoh hasilnya:

-rwxrwx---+ 1 user1 208M 2018-07-16  ./filename.bak*
-rwxrwx---+ 1 user1  702 2018-07-15  ./filename.ldf*
-rwxrwx---+ 1 user1 208M 2018-07-15  ./filename.bak*

Hal yang hebat tentang ini adalah bahwa setelah daftar telah ditinjau, itu adalah masalah sederhana untuk mengganti bagian daftar dengan findperintah delete:

find . -type f -mtime +270 -delete
Steph
sumber