En son dosyayı Linux'ta bir dizinde alın


183

Bir dizindeki en son tek dosyayı döndürecek bir komut arıyorsunuz.

İçin bir limit parametresi görmüyor ls...


1
watch -n1 'ls -Art | tail -n 1'- en son dosyaları gösterir

Buradaki yanıtların çoğu , can sıkıcı dosya adlarını işlemek için sorunlu olmayan çıktıyı ayrıştırır lsveya kullanır . : Söz her zaman yararlı BashFAQ099 bir POSIX bu soruna cevap verirfind-print0
kvantour

Yanıtlar:


266
ls -Art | tail -n 1

Çok zarif değil, ama işe yarıyor.


2
ls -Artls kullanarak dosya tarihini de görüntüleyebilirsiniz.
Josir

13
Küçük bir sorunu: Bütün bu sürümü boruları çıkışı lsiçin tail, daha sonra sadece SON çizgi yazdırır. IMHO artan düzende sıralamak ve headbunun yerine chaosönerildiği gibi kullanmak daha iyidir . İlk satır başlığı yazdırıldıktan sonra bir sonraki satırın (aslında sonraki blok) gönderilmesi SIGPIPE'yi yükseltir ve lsaynı zamanda kapanır .
TrueY

1
@TrueY Katılıyorum. Kaos'un cevabı verimlilik için daha iyidir.
dmckee --- eski moderatör yavru kedi

2
Bu çözümün dizinlerin yanı sıra dosyaları da içerdiğini unutmayın. Bu iyi ya da kötü bir şey olabilir; bireysel kullanıcının ne istediğine bağlıdır. Bunu ortaya koymamın nedeni asıl sorunun "dosya" yazması.
Sildoreth

2
Kafa yerine kuyruk kullanmanın amaçlanan yararının, ls tarafından döndürülen toplamı tanımlayan çizginin dahil edilmesini dışlamak olabileceğini düşünüyorum.
Peter Scott

155
ls -t | head -n1

Bu komut aslında geçerli çalışma dizinindeki en son değiştirilen dosyayı verir.


Benimkine eşdeğer ve muhtemelen daha verimli.
dmckee --- eski moderatör kedi yavrusu

İlk olarak benim ls bazı bilgi yankı çünkü benim için oldukça çalışmıyor, ama kullanımı olsun, teşekkürler!
bildirim

4
@Josir Tarih damgasını içerecek şekilde değiştirilebilir ls -tl | head -n 1ve tüm tabloyu benimki gibi borudan itmek zorunda değildir.
dmckee --- eski moderatör yavru kedi

1
@ noɥʇʎԀʎzɐɹƆls -t *.png | head -n1
kaos

4
Bu, en son değiştirilmişse bir klasör döndürür, şunu kullanın: ls -Art | head -n1özellikle en son değiştirilmiş dosyayı istiyorsanız
achasinh

79

Bu özyinelemeli bir sürümdür (yani en son güncellenen dosyayı belirli bir dizinde veya alt dizinlerinden herhangi birinde bulur)

find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1

Düzenleme: Kullanım -f 2-yerine -f 2Kevin önerdiği gibi


5
İşte Mac için bir çözüm:find $DIR -type f -exec stat -lt "%Y-%m-%d" {} \+ | cut -d' ' -f6- | sort -n | tail -1
Kullanıcı

2
Sorun, kesme komutunun, alanları 2 satırın sonuna döndürmek için -f 2 kullanımı -f2- yerine boşluklu yolları kesmesidir
Kevin

2
Eğer kullanarak sıralama tersine eğer kaos tarafından öneri olduğu gibi, sort -nrkullanabileceğiniz head -n 1yerine tail -n 1ve biraz verimliliğini artırmak. (Yinelemeli bir
bulguyu sıralıyorsanız

2
Çok kullanışlı! Yine de ls borulu eğer daha kolay buluyorum:find ./ -type f -printf "%T@ %p\n" -ls | sort -n | cut -d' ' -f 2- | tail -n 1 | xargs -r ls -lah
Simon

@ kullanıcının Mac sürümü saati değil, yalnızca tarihi sıralar / görüntüler. İşte sabit bir sürüm:find $DIR -type f -exec stat -lt "%F %T" {} \+ | cut -d' ' -f6- | sort -n | tail -1
yoz

11

Güvenilirlik hakkında bir not:

Yeni satır karakteri bir dosya adında olduğu gibi geçerli olduğundan , / based gibi satırlara dayanan herhangi bir çözüm kusurludur.headtail

GNU lsile başka bir seçenek, --quoting-style=shell-alwaysseçeneği ve bir bashdiziyi kullanmaktır:

eval "files=($(ls -t --quoting-style=shell-always))"
((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

( gizli dosyaları da dikkate almak istiyorsanız -Aseçeneğini ekleyin ls).

Normal dosyalarla sınırlamak istiyorsanız (dizinleri, fifo'ları, cihazları, sembolik bağlantıları, soketleri göz ardı edin), GNU'ya başvurmanız gerekir find.

Bash 4.4 veya daha yeni (for readarray -d) ve GNU coreutils 8.25 veya daha yeni (for cut -z) ile:

readarray -t -d '' files < <(
  LC_ALL=C find . -maxdepth 1 -type f ! -name '.*' -printf '%T@/%f\0' |
  sort -rzn | cut -zd/ -f2)

((${#files[@]} > 0)) && printf '%s\n' "${files[0]}"

Veya özyineli olarak:

readarray -t -d '' files < <(
  LC_ALL=C find . -name . -o -name '.*' -prune -o -type f -printf '%T@%p\0' |
  sort -rzn | cut -zd/ -f2-)

Buradaki en iyisi zsh, bashtüm bu güçlüklerden kaçınmak yerine kullanmak ve glob elemeleri olacaktır:

Geçerli dizindeki en yeni normal dosya:

printf '%s\n' *(.om[1])

Gizli olanlar dahil:

printf '%s\n' *(D.om[1])

En yeni ikinci:

printf '%s\n' *(.om[2])

Symlink çözümlemesinden sonra dosya yaşını kontrol edin:

printf '%s\n' *(-.om[1])

Tekrarlı:

printf '%s\n' **/*(.om[1])

Ayrıca, tamamlama sistemi ( compinitve birlikte) etkinleştirildiğinde, Ctrl+Xmen yeni dosyaya genişleyen bir tamamlayıcı olur.

Yani:

vi Ctrl+Xm

En yeni dosyayı düzenlemenizi sağlar (ayrıca basmadan önce hangisini görme şansınız olur Return).

vi Alt+2Ctrl+Xm

En yeni ikinci dosya için.

vi * .cCtrl+Xm

en yeni cdosya için.

vi * (.)Ctrl+Xm

en yeni normal dosya için (dizin değil, fifo / cihaz ...) vb.


zshİpuçları için teşekkürler . Bu konuda daha fazla ayrıntı için zsh dokümanlarında bir bağlantı sağlayabilir misiniz?
donduruldu

@freezed, bkzinfo zsh qualifiers
Stephane Chazelas

Stephane Chazelas
dondurulmuş

9

Kullanırım:

ls -ABrt1 --group-directories-first | tail -n1

Klasörler hariç bana sadece dosya adını veriyor.


bir dizinde sadece dizinler yoksa
ealfonso

8

ls -lAtr | tail -1

Diğer çözümler, ile başlayan dosyaları içermez '.'.

Bu komut ayrıca aşağıdakileri içerecek '.'ve '..'olmayabilecek ve içermeyecektir :

ls -latr | tail -1


Bu dönecek mi "." eğer dizin herhangi bir dosyadan daha yakın zamanda değiştirilmişse (bir silme ile söyleyin)? Belki de istenen davranış budur, belki değil. Ama her iki şekilde de haklısın.
dmckee --- eski moderatör kedi yavrusu

6

Dmckee'nin cevabına göre kısa süreli varyant:

ls -t | head -1

ancak -1sözdizimi bir süre önce kaldırılmıştır ve -n 1kullanılmalıdır.
tink

5

Sevdiğim echo *(om[1])( zshbu sadece dosya adını verir ve diğer komuta çağırmak değil yaptığı gibi sözdizimi).


1
Zsh kullanıyorsanız iyi çalışıyor. Zsh kullanmıyor musunuz? Ben bash varsayılan Ubuntu olduğunu düşünüyorum; zsh yükleyebilir veya bash için eşdeğer bir komut bulabilirsiniz.
MikeB

3
Komut "echo" dur; sadece parametrelerini değerlendirir ve standart çıktıya gönderir. Bu durumda, glob niteleyicisi "om [1]", "o" 'ya sahiptir; bu, eşleşen dosyaların "m" ile düzenlenmesi anlamına gelir; Ve bu sıralı listeden, ilk dosya olan [1] 'i ele alalım. Glob
MikeB

4

Bul / sırala çözümü, dosya sayısı gerçekten büyüyene kadar (tüm dosya sistemi gibi) harika çalışır. En son dosyayı takip etmek için awk komutunu kullanın:

find $DIR -type f -printf "%T@ %p\n" | 
awk '
BEGIN { recent = 0; file = "" }
{
if ($1 > recent)
   {
   recent = $1;
   file = $0;
   }
}
END { print file; }' |
sed 's/^[0-9]*\.[0-9]* //'

3

Kişisel olarak mümkün olduğunca az sayıda yerleşik olmayan bashkomut kullanmayı tercih ediyorum (pahalı çatal ve exec sistem çağrılarının sayısını azaltmak için). Tarihe göre sıralamak için aranması lsgerekiyor. Ancak, headkullanımı gerçekten gerekli değildir. Aşağıdaki tek astarı kullanıyorum (yalnızca ad borularını destekleyen sistemlerde çalışır):

read newest < <(ls -t *.log)

veya en eski dosyanın adını almak için

read oldest < <(ls -rt *.log)

(İki '<' işareti arasındaki boşluğa dikkat edin!)

Gizli dosyalar da gerekiyorsa -bir arg eklenebilir.

Umarım bu yardımcı olabilir.


Dosya adının $ oldest / newest var. Ancak en az çatal için +1.
squareatom

@squareatom Ben okudum yerleşik oldukça iyi biliyorum düşündüm. Ama haklısın, belki de değil. Yorumun için teşekkürler!
True

3
Yerleşik bir öğenin ne olduğunu bildiğinizi varsayarsak, haklısınız. Ama ben sadece OP'nin sorusunu düşünüyordum. Bir şey döndürecek bir emir istediler. Teknik olarak çözümünüz hiçbir şey vermez. Yani "&& echo $ newest" ya da sonuna
ekleyin

3

R özyinelemeli seçeneğini kullanarak .. burada iyi yanıtlar için bir geliştirme olarak düşünebilirsiniz

ls -arRtlh | tail -50

2
ls -t -1 | sed '1q'

Klasördeki son değiştirilen öğeyi gösterir. grepAnahtar kelimelerle en son girişleri bulmak için ile eşleştirin

ls -t -1 | grep foo | sed '1q'

'1q' nedir? 1ilk satır head -n 1için q nedir?
HattrickNZ

2

Tekrarlı:

find $1 -type f -exec stat --format '%Y :%y %n' "{}" \; | sort -nr | cut -d: -f2- | head

1

bu basit komutu dene

ls -ltq  <path>  | head -n 1

Dosya adını istiyorsanız - son değiştirilme tarihi: path = /ab/cd/*.log

Dizin adı - son değiştirilme tarihi istiyorsanız, path = / ab / cd / * /


1

Bir ile başlayan gizli dosyaları umursamadığınızı varsayarsak .

ls -rt | tail -n 1

Aksi takdirde

ls -Art | tail -n 1


0

Tüm bu ls / tail çözümleri, bir dizindeki - alt dizinleri yok sayar.

Aramanıza tüm dosyaları dahil etmek için (özyinelemeli olarak) find kullanılabilir. gioele, biçimlendirilmiş bulma çıktısının sıralanmasını önerdi. Ancak beyaz boşluklara dikkat edin (önerisi beyaz boşluklarla çalışmaz).

Bu, tüm dosya adlarıyla çalışmalıdır:

find $DIR -type f -printf "%T@ %p\n" | sort -n | sed -r 's/^[0-9.]+\s+//' | tail -n 1 | xargs -I{} ls -l "{}"

Bu zamana göre sıralıyor, bkz.

%Ak    File's  last  access  time in the format specified by k, which is either `@' or a directive for the C `strftime' function.  The possible values for k are listed below; some of them might not be available on all systems, due to differences in `strftime' between systems.
       @      seconds since Jan. 1, 1970, 00:00 GMT, with fractional part.
%Ck    File's last status change time in the format specified by k, which is the same as for %A.
%Tk    File's last modification time in the format specified by k, which is the same as for %A.

Yani sadece ctime %Tile %Csıralamak için ile değiştirin .


@Gioele önerisiyle beyaz boşluk sorunu hakkında haklısınız, ancak bunu düzeltmek için bir aralık yapmak için -f seçeneğine yalnızca bir tire işareti eklemeniz gerekir: find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1 Veya alternatif olarak, ilk alan hariç tümünü saklayın: find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 1 --complement | tail -n 1
Aaron

0

Bir desene göre her dizindeki en güncel dosyayı bulma, örneğin "tmp" ile biten çalışma dizininin alt dizinleri (büyük / küçük harf duyarsız):

find . -iname \*tmp -type d -exec sh -c "ls -lArt {} | tail -n 1" \;

0
ls -Frt | grep "[^/]$" | tail -n 1

1
OP'nin sorusunu sağlayan başka cevaplar da var ve yıllar önce yayınlandı. Bir yanıt gönderirken, lütfen özellikle eski soruları yanıtlarken yeni bir çözüm veya çok daha iyi bir açıklama eklediğinizden emin olun.
help-info.de

2
@ help-info.de Lütfen yalnızca kod içeren yanıtları silmek için oy vermeyin. Harika olmayabilirler, ancak silme cevap olmayan şeyler içindir
Machavity

@Machavity - Umarım başarısız olmaz ve sadece geç cevap için bir yorum yaptım.
help-info.de

0

Herhangi bir alt dizin de dahil olmak üzere en son değiştirilen dosyayı almak istiyorsanız, bu küçük oneliner ile yapabilirsiniz:

find . -type f -exec stat -c '%Y %n' {} \; | sort -nr | awk -v var="1" 'NR==1,NR==var {print $0}' | while read t f; do d=$(date -d @$t "+%b %d %T %Y"); echo "$d -- $f"; done

Aynı şeyi değiştirilen dosyalar için değil, erişilen dosyalar için basitçe

Stat komutundan % X parametresine % Y parametresi . Ve en son erişilen dosyalar için komutunuz şöyle görünür:

find . -type f -exec stat -c '%X %n' {} \; | sort -nr | awk -v var="1" 'NR==1,NR==var {print $0}' | while read t f; do d=$(date -d @$t "+%b %d %T %Y"); echo "$d -- $f"; done

Her iki komut için de birden fazla dosya listelemek istiyorsanız var = "1" parametresini değiştirebilirsiniz .


-1

Ben de yapmam gerekiyordu ve bu komutları buldum. bunlar benim için çalışıyor:

Son dosyayı klasörde oluşturulma tarihine göre istiyorsanız (erişim zamanı):

ls -Aru | tail -n 1  

Ve içeriğinde değişiklik olan son dosyayı istiyorsanız (zamanı değiştir):

ls -Art | tail -n 1  
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.