Değişiklik tarihine göre ardışık olarak sıralanmış dosyalar nasıl listelenir (stat komutu mevcut değil!)


31

Geçerli dizindeki tüm dosyaların değiştirilme tarihleriyle birlikte o tarihe göre sıralanmasını nasıl sağlayabilirim?

Şimdi bunu nasıl başarabileceğimi biliyorum find, statve sort, ama bazı tuhaf sebeplerden dolayı statkutuya kurulmamış ve kurmam mümkün değil.

Başka seçenek var mı?

Not: gccyüklü değil


Derlenmiş bir ikili dosya yükleyip orada çalıştırabilir misiniz?
imz - Ivan Zakharyaschev 14:11

@ imz: evet, gitmek için başka bir yol. find -printfEylem en kolay olsa gibi görünüyor.
alex

Yanıtlar:


27

En kısa yöntemim zsh kullanır:

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

( Dgizli dosyaları veya gizli dizinlerdeki dosyaları da listelemek istiyorsanız glob niteleyicileri ekleyin ).

Eğer GNU bulursanız, dosya değiştirme zamanlarını yazdırmasını ve buna göre sıralamasını sağlayın. Dosya adlarında yeni satırlar olmadığını varsayıyorum.

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

Perl'niz varsa (yine, dosya adlarında yeni satırlar olmadığını varsayarak):

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

Python'unuz varsa (yine, dosya adlarında yeni satırlar olmadığını varsayarak):

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'

Bu sunucuya SSH erişiminiz varsa, dizini daha iyi donanımlı bir makinede sshfs üzerine bağlayın:

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

Yalnızca POSIX araçlarıyla, çok daha karmaşık, çünkü bir dosyanın değiştirilme zamanını bulmanın iyi bir yolu yok. Bir dosyanın zamanlarını almanın tek standart yolu lsve çıktı formatı yerel ayarlara bağlıdır ve ayrıştırılması zordur.

Dosyalara yazabiliyorsanız ve yalnızca normal dosyaları önemsiyorsanız ve dosya adlarında yeni satırlar yoksa, işte korkunç bir kludge: tek bir dizindeki tüm dosyalara sert bağlantılar oluşturun ve bunları değişiklik zamanına göre sıralayın.

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

En kolay yol muhtemelen find . -print | xargs -n99999 -s999999 ls -ltr. Ancak bu, (1) 512'den büyük veya 5120'den büyük olmasına xargsizin vermeyebilir ve (b) bu sorunu çözebilseniz bile, hâlâ birleşik argüman listesi ve ortamının bir çekirdek empoze edilmiş maksimum boyutu vardır. Fikirlerinin çoğu (Perl ve Python'u koru) aynı problemi yaşatıyor, bu yüzden özellikle uzun komut satırları oluşturmaktan kaçındım. -m-s
geekosaur,

Özellikle, zshgenel durumdaki özyinelemeli globları kullanarak düzenli aralıklarla "çok uzun argüman listesi" hataları alıyorum .
geekosaur,

@geekosaur: Sadece son korkunç çamurun uzun komut satırlarında bir sorunu var. Zsh'de yerleşiklerle çok şey yapabilirsiniz (örneğin print -rl **/*, tek sınır ne kadar boş hafızaya sahip olduğunuzdur) ve bunun ötesinde zargs. Teklifiniz yalnızca bir kez çağrılmayı bitirirse find … | xargs … lsdoğru şekilde sıralanır ve dosya adlarında özel karakterler varsa işe yaramaz. xargsls
Gilles 'SO- kötülük' dur

çok seçenek ile son derece detaylı cevap için çok teşekkürler! :)
alex

İşte bu yüzden zsh'yi seviyorum.
Profpatsch

14

GNU varsayarak find:

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

Değişim 1n,1için 1nr,1dosyaları isterseniz en son ilk listede.

Eğer GNU'nuz yoksa finddaha zor hale gelir, çünkü lszaman damgası formatı çok değişkendir (örneğin yakın zamanda değiştirilen dosyalar farklı bir zaman damgası stiline sahiptir).


Aslında tarih ve saat biçimini şu şekilde de değiştirebilirsiniz ls --time-style="..."- Bunun standart mı yoksa GNU mu, GNU mu olduğundan emin değilim.
asoundmove

Kesinlikle GNU.
geekosaur,

@ asoundmove: ne yazık ki, kutu çok eski (RedHat 7.2) ve lsbu seçeneğe sahip değil.
alex

7

Bir macta bulmak için -printf argümanı yoktur, ancak bunun yerine bunu yapabilirsiniz:

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



0

Gizli dosyaları görmezden gelme - güzel ve hızlı zaman damgasıyla

Dosya adlarındaki boşlukları iyi işler - bunları kullanmamalısınız!

$ 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

Daha findbolcaBağlantıyı takip ederek bulunabiliyor.


0

Genellikle dosyaları tarihe göre bulmaktan bahseder (bu, asıl poster için işe yaramaz, ama ben burada bitirdim, bu yüzden başkalarının da yapabileceğini düşündüm). Kullanım durumumda, dosyaları silmeden önce gözden geçirmek amacıyla listelemek istiyorum.

4.6.0 findutils ile beğendim:

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

Yukarıdaki komut -type f, geçerli çalışma dizininde ( .) 270 günden daha önce değiştirilmiş dosyaları ( ) bulur ( -mtime +270Ayrıca -mtime 0, son 24 saati üretecektir ve-mtime -5 son 5 günü ). Daha sonra kullandığı lstarihe göre bunları listelemek için, ilk en yeni ( -exec ls -laFGht --time-style=iso {} \+)

İşte çıktının bir örneği:

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

Bununla ilgili harika bir şey, liste gözden geçirildikten sonra, liste bölümünün finddelete komutuyla değiştirilmesi basit bir konudur :

find . -type f -mtime +270 -delete
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.