Bir dizindeki en son değiştirilen dosyayı özyinelemeli olarak nasıl bulabilirim?


Yanıtlar:


357
find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" "

Büyük bir ağaç için, sorther şeyi hafızada tutmak zor olabilir .

%T@bir unix zaman damgası gibi değişiklik süresini verir, sort -nsayısal olarak sıralar tail -1, son satırı (en yüksek zaman damgası) alır, cut -f2 -d" "ilk alanı (zaman damgası) çıktıdan keser.

Düzenleme:-printf Muhtemelen sadece GNU gibi , ajreals kullanımı stat -cda. Aynı şeyi BSD'de yapmak mümkün olsa da, biçimlendirme seçenekleri farklıdır ( -f "%m %N"görünecektir)

Ve çoğul kısmını özledim; Daha sonra isterseniz son dosyayı, sadece kuyruk argümanı yükseltmek.


7
Sipariş önemliyse, sort -rn | head -3bunun yerine kullanımı değiştirebilirsiniz sort -n | tail -3. Bir sürüm dosyaları en eskiden en yeniye verirken diğeri en yeniden en eskiye doğru verir.
Don Faulkner

3
Büyük bir dizin vardı (yaklaşık on binlerce küçük dosya) ve performans hakkında endişelendim, ama ... bu komut bir saniyeden daha kısa sürede çalışıyor! Harika, çok teşekkürler !!! :-)
lucaferrario

2
"Büyük bir ağaç için her şeyi hafızasında tutmak zor olabilir." gerektiğinde sortgeçici dosyalar (in /tmp) oluşturacaktır , bu yüzden bunun bir endişe olduğunu düşünmüyorum.
Vladimir Panteleev

1
üzerinde değişiklik yapmak: -printf '%T@ %Tb %Td %TY %p\n'size bir tarih damgası verir (gerekirse ls)
bshea

1
Aşağıdaki kısa ve daha yorumlanabilir çıktı ile buluyorum:find . -type f -printf '%TF %TT %p\n' | sort | tail -1
snth

129

Takip etmek @ plundra cevabı , burada BSD ve OS X sürümü:

find . -type f -print0 | xargs -0 stat -f "%m %N" |
sort -rn | head -1 | cut -f2- -d" "

1
BSD / OS X yerine finddestekliyor mu? Çünkü bu aynı şeyi yapar (parametre olarak birden fazla dosyayı geçirerek), boru olmadan . +\;-print0 | xargs -0
DevSolar

Son 5 veya n dosya sayısını azalan sırada değiştirmek istersem ne yapmam gerekir?
khunshan

@khunshan değiştirmek head -1içinhead -5
Emerson Farrugia

20

Sonuçları sıralamak ve yalnızca son değiştirilenleri tutmak yerine, yalnızca en büyük değişiklik süresine sahip olanı (unix zamanında) yazdırmak için awk kullanabilirsiniz:

find . -type f -printf "%T@\0%p\0" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\0'

Dosya sayısı yeterince büyükse, bu sorununuzu çözmenin daha hızlı bir yolu olmalıdır.

Teorik olarak, bir dosya adı (boşluk ve satırsonu dahil) herhangi bir karakter içerebilir, çünkü NUL karakteri (yani '\ 0') kullandım.

Sisteminizde böyle patolojik dosya adlarınız yoksa, yeni satır karakterini de kullanabilirsiniz:

find . -type f -printf "%T@\n%p\n" | awk '
    {
        if ($0>max) {
            max=$0; 
            getline mostrecent
        } else 
            getline
    } 
    END{print mostrecent}' RS='\n'

Buna ek olarak, bu mawk da çalışır.


Bu, en son üçünü korumak için kolayca uyarlanabilir.
sonraki duyuruya kadar duraklatıldı.

1
Bu mawkDebian standart alternatifi ile çalışmaz .
Ocak

Hayır, ancak bu durumda sizi rahatsız etmiyorsa newline karakterini kullanabilirsiniz;)
marco

10

Solaris 10 altında en son değiştirilen dosyayı bulmakta sorun yaşadım find. printfSeçenek yok ve statmevcut değil. Benim için uygun olan aşağıdaki çözümü keşfettim:

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7 }' | sort | tail -1

Dosya adını da göstermek için

find . -type f | sed 's/.*/"&"/' | xargs ls -E | awk '{ print $6," ",$7," ",$9 }' | sort | tail -1

açıklama

  • find . -type f tüm dosyaları bulur ve listeler
  • sed 's/.*/"&"/' boşlukları işlemek için yol adını tırnak işaretleri içine alır
  • xargs ls -Ekote yolunu gönderir ls, -Eseçenek tam zaman damgası (biçim emin olur yıl-ay-gün saat dakika-saniye-nanosaniye ) döndürülür
  • awk '{ print $6," ",$7 }' sadece tarih ve saati ayıklar
  • awk '{ print $6," ",$7," ",$9 }' tarih, saat ve dosya adını ayıklar
  • sort dosyaları tarihe göre sıralanmış olarak döndürür
  • tail -1 yalnızca son değiştirilen dosyayı döndürür

9

Bu, alt dizinlerle bile iyi çalışıyor gibi görünüyor:

find . -type f | xargs ls -ltr | tail -n 1

Çok fazla dosya olması durumunda, bulmayı daraltın.


1
-lSeçeneği lsgereksiz görünüyor. Sadece -tryeterli görünüyor.
Acumenus

6
Bu dizin başına sıralanıyor gibi görünüyor, bu yüzden mutlaka en son dosyayı göstermez
Fabian Schmengler

1
Dosya yollarında boşluk olması durumunda:find . -type f -print0 | xargs -0 ls -ltr | tail -n 1
Periyodik Bakım

Bu benim için en yeni dosyaları bulamıyor.
K.-Michael Aye

1
Dosya adlarında boşluk varsa bunun kırıldığını düşünün
waferthin

7

İnsan tarafından okunabilir zaman damgası içeren en son dosyayı gösterir:

find . -type f -printf '%TY-%Tm-%Td %TH:%TM: %Tz %p\n'| sort -n | tail -n1

Sonuç şuna benzer:

2015-10-06 11:30: +0200 ./foo/bar.txt

Daha fazla dosya göstermek için daha -n1yüksek bir sayıyla değiştirin


5

Her zaman benzer bir şey ve en son değiştirilen dosyaların top-k listesini kullanıyorum. Büyük dizin ağaçları için, sıralamayı önlemek çok daha hızlı olabilir . Yalnızca en son değiştirilen ilk 1 dosya için:

find . -type f -printf '%T@ %p\n' | perl -ne '@a=split(/\s+/, $_, 2); ($t,$f)=@a if $a[0]>$t; print $f if eof()'

1.7 milyon dosya içeren bir dizinde, 3.4s'de en sonuncuyu alıyorum, sıralama kullanarak 25.5s çözümüne karşı 7.5x hız.


Çok havalı: Son baskıyı tarihle de güzel bir şekilde görmek için system ("ls -l $ f") if eof () ile değiştirdim.
Martin T.

@MartinT. : harika ve rica ederim. Bir O (n) yöntemi mevcut olduğunda insanların bu tür şeyleri (O (n log n)) sıralama içgüdüsüne sahip olması garip. Sıralamayı önleyen tek cevap bu gibi görünüyor. BTW, önerdiğim komutun amacı sadece en son dosyanın yolunu bulmak. Kabuğunuzdaki komutu taklit edebilirsiniz (örn. Gibi lastfile) ve sonra sonuçla istediğiniz gibi yapabilirsiniz ls -l $(lastfile .), ya da open $(lastfile .)(Mac'te), vb.
Pierre D

Düzeltilmiş duruyorum: Aşağıda başka bir cevap görüyorum (@marco). +1.
Pierre D

4

Bu sıralanmış bir liste verir:

find . -type f -ls 2>/dev/null | sort -M -k8,10 | head -n5

Sort komutuna '-r' yerleştirerek sıralamayı tersine çevirin. Yalnızca dosya adları istiyorsanız, "awk '{print $ 11}' |" önce '| kafa'


3

Ubuntu 13'te, aşağıdakileri yapar, belki biraz daha hızlıdır, çünkü sıralamayı tersine çevirir ve 'kuyruk' yerine 'kafa' kullanır ve işi azaltır. Bir ağaçtaki en yeni 11 dosyayı göstermek için:

bulmak. tipi f -printf '% T @% p \ n' | sıralama -n -r | kafa -11 | kes -f2- -d "" | sed -e 's, ^. / ,,' | xargs ls -U -l

Bu, yeniden sıralama yapmadan tam bir ls listesi verir ve can sıkıcı './' 'bul' her dosya adını koyar.

Veya bash işlevi olarak:

treecent () {
  local numl
  if [[ 0 -eq $# ]] ; then
    numl=11   # Or whatever default you want.
  else
    numl=$1
  fi
  find . -type f -printf '%T@ %p\n' | sort -n -r | head -${numl} |  cut -f2- -d" " | sed -e 's,^\./,,' | xargs ls -U -l
}

Yine de, çalışmaların çoğu plundra'nın orijinal çözümü tarafından yapıldı. Teşekkürler plundra.


3

Aynı sorunla karşılaştım. En son dosyayı özyinelemeli bulmam gerekiyor. bulmak için yaklaşık 50 dakika sürdü.

İşte daha hızlı yapmak için küçük bir komut dosyası:

#!/bin/sh

CURRENT_DIR='.'

zob () {
    FILE=$(ls -Art1 ${CURRENT_DIR} | tail -n 1)
    if [ ! -f ${FILE} ]; then
        CURRENT_DIR="${CURRENT_DIR}/${FILE}"
        zob
    fi
    echo $FILE
    exit
}
zob

Bir dizinin en son değiştirilen öğesini alan özyinelemeli bir işlevdir. Bu öğe bir dizinse, işlev özyinelemeli olarak adlandırılır ve bu dizinde vb.


3

Aşağıdaki kısa ve daha yorumlanabilir çıktı ile buluyorum:

find . -type f -printf '%TF %TT %p\n' | sort | tail -1

Standartlaştırılmış ISO formatının sabit zamanları göz önüne alındığında, sözlükbilimsel sıralama iyidir ve -n seçeneğe .

Zaman damgalarını tekrar kaldırmak istiyorsanız şunları kullanabilirsiniz:

find . -type f -printf '%TFT%TT %p\n' | sort | tail -1 | cut -f2- -d' '

2

statHer dosyada ayrı ayrı çalışan yavaşlamak istiyorsanız, xargsişleri biraz hızlandırmak için kullanabilirsiniz :

find . -type f -print0 | xargs -0 stat -f "%m %N" | sort -n | tail -1 | cut -f2- -d" " 

2

Bu, geçerli dizindeki tüm dizinlerin değiştirilme süresini her dizindeki en yeni dosyaya yinelemeli olarak değiştirir:

for dir in */; do find $dir -type f -printf '%T@ "%p"\n' | sort -n | tail -1 | cut -f2- -d" " | xargs -I {} touch -r {} $dir; done

1
Herhangi bir dirs boşluk içeriyorsa kötü bir şekilde kırılır - IFS'yi ayarlamanız ve tırnak işaretleri kullanmanız gerekir: IFS = $ '\ n'; $ dir (find ./ -type d) için; echo "$ dir" yap; "$ dir" türünü bulun f -printf '% T @ "% p" \ n' | sıralama -n | kuyruk -1 | kes -f2- -d "" | xargs -I {} dokunma -r {} "$ dir"; yapılan;
Andy Lee Robinson

2

Bu basit klibi de çalışacak:

ls -1t | head -1

-1 değerini listelemek istediğiniz dosya sayısına değiştirebilirsiniz


10
Hayır, özyinelemediğinden olmayacaktır.
arataj

1

Yukarıdaki komutu kullanışlı buldum, ancak benim durumum için dosyanın tarihini ve saatini görmem gerekiyordu, ayrıca adlarda boşluk olan birkaç dosyayla ilgili bir sorunum vardı. İşte benim çalışma çözümüm.

find . -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -f2- -d" " | sed 's/.*/"&"/' | xargs ls -l

1

Solaris üzerinde aşağıdaki komut çalıştı:

find . -name "*zip" -type f | xargs ls -ltr | tail -1 

1

Gizli dosyaları yok saymak - güzel ve hızlı zaman damgası ile

$ find . -type f -not -path '*/\.*' -printf '%TY.%Tm.%Td %THh%TM %Ta %p\n' |sort -nr |head -n 10

Sonuç

Dosya adlarındaki boşlukları iyi işler - bunların kullanılması gerekmez!

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

findBağlantıyı takiben daha fazla bolluk.


1

/ Target_directory ve tüm alt dizinlerindeki son 60 dakika içinde değiştirilmiş dosyaları aramak için:

$ find /target_directory -type f -mmin -60

En son değiştirilen dosyaları, güncelleme süresinin ters sırasına göre sıralanmış olarak bulmak için (yani, en son güncellenen dosyalar önce):

$ find /etc -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort -r

0

Bunu tercih ederim, daha kısa:

find . -type f -print0|xargs -0 ls -drt|tail -n 1

0

Bu soru için bir pypi / github paketi yazdım çünkü bir çözüme de ihtiyacım vardı.

https://github.com/bucknerns/logtail

Yüklemek:

pip install logtail

Kullanım: kuyrukları değiştirilen dosyaları

logtail <log dir> [<glob match: default=*.log>]

Kullanım2: En son değiştirilen dosyayı düzenleyicide açar

editlatest <log dir> [<glob match: default=*.log>]
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.