Dapatkan file terbaru di direktori di Linux

183

Mencari perintah yang akan mengembalikan satu file terbaru dalam direktori.

Tidak melihat parameter batas ke ls...

ack
sumber
1
watch -n1 'ls -Art | tail -n 1'- menunjukkan file terakhir
Sebagian besar jawaban di sini menguraikan output lsatau penggunaan findtanpa -print0yang bermasalah untuk menangani nama file yang mengganggu. Selalu berguna untuk menyebutkan: BashFAQ099 yang memberikan jawaban POSIX untuk masalah ini
kvantour

Jawaban:

266
ls -Art | tail -n 1

Tidak terlalu elegan, tetapi berhasil.

dmckee --- mantan kucing moderator
sumber
2
menggunakan ls -Artl Anda juga dapat melihat tanggal file.
Josir
13
Masalah kecil: Versi ini mem-pipe semua output lske tail, kemudian hanya mencetak garis LAST. IMHO lebih baik untuk mengurutkan dalam urutan naik dan gunakan headsebagai gantinya, seperti yang chaosdisarankan. Setelah mencetak kepala baris pertama berhenti, jadi mengirim baris berikutnya (sebenarnya blok berikutnya) akan naik SIGPIPE dan lsakan berhenti juga.
Benar
1
@ Benar saya cukup setuju. Jawaban Chaos lebih baik untuk efisiensi.
dmckee --- ex-moderator kitten
2
Perhatikan bahwa solusi ini mencakup direktori serta file. Ini bisa menjadi hal yang baik atau buruk; itu tergantung pada apa yang diinginkan pengguna individu. Alasan saya mengemukakan ini adalah karena pertanyaan aslinya mengatakan "file".
Sildoreth
2
Saya berpikir bahwa manfaat yang dimaksudkan dari menggunakan ekor daripada kepala mungkin untuk mengecualikan dimasukkannya garis yang menggambarkan total yang dikembalikan oleh ls.
Peter Scott
155
ls -t | head -n1

Perintah ini sebenarnya memberikan file yang dimodifikasi terbaru di direktori kerja saat ini.

kekacauan
sumber
Setara dengan saya, dan mungkin lebih efisien juga.
dmckee --- mantan moderator anak kucing
tidak cukup bekerja untuk saya karena saya menggemakan beberapa info di ls saya terlebih dahulu, tetapi saya mendapatkan penggunaannya, terima kasih!
ack
4
@Josir Ini dapat dimodifikasi untuk menyertakan datestamp ls -tl | head -n 1, dan itu tidak harus mendorong seluruh tabel melalui pipa seperti yang dilakukan tambang.
dmckee --- ex-moderator kitten
1
@ noɥʇʎԀʎzɐɹƆls -t *.png | head -n1
kekacauan
4
Ini mengembalikan folder jika itu adalah yang terbaru dimodifikasi, gunakan: ls -Art | head -n1jika Anda secara spesifik menginginkan file yang dimodifikasi terbaru
achasinh
79

Ini adalah versi rekursif (yaitu menemukan file yang paling baru diperbarui di direktori tertentu atau salah satu subdirektori)

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

Sunting: gunakan -f 2-alih-alih -f 2seperti yang disarankan oleh Kevin

gioele
sumber
5
Inilah solusi untuk Mac:find $DIR -type f -exec stat -lt "%Y-%m-%d" {} \+ | cut -d' ' -f6- | sort -n | tail -1
pengguna
2
Masalahnya adalah perintah cut memotong jalur dengan spasi bukannya -f 2 gunakan -f2- untuk mengembalikan bidang 2 ke akhir baris
Kevin
2
Seperti dalam saran oleh kekacauan, jika Anda membalikkan pengurutan dengan menggunakan sort -nr, Anda dapat menggunakan head -n 1alih-alih tail -n 1dan sedikit meningkatkan efisiensi. (Meskipun jika Anda mengurutkan penemuan rekursif, mendapatkan baris pertama atau terakhir tidak akan menjadi bagian yang lambat.)
destenson
2
Sangat berguna! Saya merasa lebih ramah jika disalurkan ke ls:find ./ -type f -printf "%T@ %p\n" -ls | sort -n | cut -d' ' -f 2- | tail -n 1 | xargs -r ls -lah
Simon
@ Mac versi pengguna hanya mengurutkan / menampilkan tanggal, bukan waktu. Ini versi yang sudah diperbaiki:find $DIR -type f -exec stat -lt "%F %T" {} \+ | cut -d' ' -f6- | sort -n | tail -1
yoz
11

Catatan tentang keandalan:

Karena karakter baris baru sama validnya dengan nama file, solusi apa pun yang bergantung pada baris seperti yang berbasis head/ tailcacat.

Dengan GNU ls, opsi lain adalah menggunakan --quoting-style=shell-alwaysopsi dan basharray:

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

(tambahkan -Aopsi lsjika Anda juga ingin mempertimbangkan file tersembunyi).

Jika Anda ingin membatasi ke file biasa (abaikan direktori, fifos, perangkat, symlink, soket ...), Anda harus beralih ke GNU find.

Dengan bash 4.4 atau yang lebih baru (untuk readarray -d) dan GNU coreutils 8.25 atau yang lebih baru (untuk cut -z):

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]}"

Atau secara rekursif:

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

Yang terbaik di sini adalah menggunakan zshdan kualifikasi globalnya alih-alih bashmenghindari semua kerumitan ini:

File reguler terbaru di direktori saat ini:

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

Termasuk yang tersembunyi:

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

Terbaru kedua:

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

Periksa usia file setelah resolusi symlink:

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

Secara rekursif:

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

Juga, dengan sistem penyelesaian ( compinitdan co) diaktifkan, Ctrl+Xmmenjadi pelengkap yang memperluas ke file terbaru.

Begitu:

vi Ctrl+Xm

Akan membuat Anda mengedit file terbaru (Anda juga mendapatkan kesempatan untuk melihatnya sebelum Anda menekan Return).

vi Alt+2Ctrl+Xm

Untuk file terbaru kedua.

vi * .cCtrl+Xm

untuk cfile terbaru .

vi * (.)Ctrl+Xm

untuk file reguler terbaru (bukan direktori, atau fifo / perangkat ...), dan sebagainya.

Stephane Chazelas
sumber
Terima kasih atas zshtipsnya. Bisakah Anda memberikan tautan ke detail lebih lanjut tentang ini di dokumen zsh?
dibekukan
@gratis, lihatinfo zsh qualifiers
Stephane Chazelas
Terima kasih @Stephane Chazelas
dibekukan
9

Saya menggunakan:

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

Ini memberi saya hanya nama file, tidak termasuk folder.

pengguna1195354
sumber
kecuali direktori hanya memiliki direktori
ealfonso
8

ls -lAtr | tail -1

Solusi lain tidak termasuk file yang dimulai dengan '.'.

Perintah ini juga akan mencakup '.'dan '..', yang mungkin atau tidak sesuai dengan yang Anda inginkan:

ls -latr | tail -1

Jared Oberhaus
sumber
Akankah ini kembali "." jika direktori telah dimodifikasi lebih baru daripada file yang ada (katakanlah dengan penghapusan)? Mungkin itu perilaku yang diinginkan, mungkin juga tidak. Tapi kau benar juga.
dmckee --- ex-moderator kitten
6

Varian singkat berdasarkan jawaban dmckee:

ls -t | head -1
Dmytro G. Sergiienko
sumber
tetapi -1sintaks untuk kepala telah ditinggalkan beberapa waktu yang lalu, dan -n 1harus digunakan.
tink
5

Saya suka echo *(om[1])( zshsintaks) karena hanya memberikan nama file dan tidak meminta perintah lain.

MikeB
sumber
1
Bekerja dengan baik jika Anda menggunakan zsh. Apakah Anda tidak menggunakan zsh? Saya pikir bash adalah default di Ubuntu; Anda dapat menginstal zsh, atau Anda dapat menemukan perintah setara untuk bash.
MikeB
3
Perintahnya adalah "echo"; itu hanya mengevaluasi parameternya dan mengirimkannya ke output standar. Dalam hal ini, kualifikasi glob "om [1]" memiliki "o", yang berarti memesan file yang cocok dengan "m", yang merupakan waktu yang dimodifikasi. Dan dari daftar yang dipesan itu, ambil [1], yang merupakan file pertama. Anda dapat membaca tentang kualifikasi glob: zsh.sourceforge.net/Doc/Release/Expansion.html#Glob-Qualifiers
MikeB
4

Solusi find / sort berfungsi dengan baik hingga jumlah file menjadi sangat besar (seperti seluruh sistem file). Gunakan awk sebagai gantinya untuk hanya melacak file terbaru:

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]* //'
Patrick
sumber
3

Saya pribadi lebih suka menggunakan beberapa bashperintah tidak built-in yang saya bisa (untuk mengurangi jumlah garpu dan syscalls exec mahal). Untuk mengurutkan berdasarkan tanggal lsperlu dipanggil. Tetapi penggunaan headtidak benar-benar diperlukan. Saya menggunakan satu-liner berikut (hanya bekerja pada sistem yang mendukung pipa nama):

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

atau untuk mendapatkan nama file terlama

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

(Pikirkan ruang antara dua '<' tanda!)

Jika file tersembunyi juga diperlukan -A arg dapat ditambahkan.

Saya harap ini bisa membantu.

Benar
sumber
Anda harus menjelaskan bahwa nama file disimpan dalam $ tertua / terbaru. Tapi +1 untuk jumlah garpu terkecil.
squareatom
@squareatom saya pikir baca cukup baik tahu built-in. Tapi kamu benar, mungkin juga tidak. Terima kasih atas komentar Anda!
TrueY
3
Dengan asumsi Anda tahu apa itu built-in, Anda mungkin benar. Tapi, saya hanya memikirkan pertanyaan OP. Mereka meminta perintah yang akan mengembalikan sesuatu. Secara teknis solusi Anda tidak menghasilkan apa-apa. Jadi tambahkan saja "&& echo $
latest
3

menggunakan opsi R rekursif .. Anda dapat menganggap ini sebagai peningkatan untuk jawaban yang baik di sini

ls -arRtlh | tail -50
mebada
sumber
2
ls -t -1 | sed '1q'

Akan menampilkan item yang dimodifikasi terakhir di folder. Pasangkan dengan grepuntuk menemukan entri terbaru dengan kata kunci

ls -t -1 | grep foo | sed '1q'
Richard Servello
sumber
apa '1q'? 1adalah untuk baris pertama equiv untuk head -n 1apa q?
HattrickNZ
2

Secara rekursif:

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

coba perintah sederhana ini

ls -ltq  <path>  | head -n 1

Jika Anda ingin nama file - terakhir dimodifikasi, path = /ab/cd/*.log

Jika Anda ingin nama direktori - terakhir diubah, path = / ab / cd / * /

RICHA AGGARWAL
sumber
1

Menganggap Anda tidak peduli dengan file tersembunyi yang dimulai dengan a .

ls -rt | tail -n 1

Jika tidak

ls -Art | tail -n 1
jasonleonhard
sumber
1

Dengan hanya Bash bawaan, mengikuti BashFAQ / 003 :

shopt -s nullglob

for f in * .*; do
    [[ -d $f ]] && continue
    [[ $f -nt $latest ]] && latest=$f
done

printf '%s\n' "$latest"
Benjamin W.
sumber
0

Semua ls orang / solusi ekor bekerja baik-baik saja untuk file dalam sebuah direktori - mengabaikan subdirektori.

Untuk memasukkan semua file dalam pencarian Anda (secara rekursif), find dapat digunakan. gioele menyarankan untuk menyortir hasil pencarian yang diformat. Tapi hati-hati dengan spasi putih (sarannya tidak bekerja dengan spasi putih).

Ini harus bekerja dengan semua nama file:

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

Ini semacam jam, lihat pria menemukan:

%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.

Jadi ganti saja %Tdengan %Cmengurutkan berdasarkan waktu.

basic6
sumber
Anda benar tentang masalah ruang putih dengan saran @gioele, tetapi Anda hanya perlu menambahkan tanda hubung ke opsi -f untuk menjadikannya rentang untuk memperbaikinya: find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 2- | tail -n 1 Atau sebagai alternatif, simpan semua kecuali bidang pertama: find $DIR -type f -printf "%T@ %p\n" | sort -n | cut -d' ' -f 1 --complement | tail -n 1
Aaron
0

Menemukan file terbaru di setiap direktori sesuai dengan suatu pola, misalnya sub direktori direktori kerja yang memiliki nama yang diakhiri dengan "tmp" (tidak sensitif huruf besar-kecil):

find . -iname \*tmp -type d -exec sh -c "ls -lArt {} | tail -n 1" \;
xb.
sumber
0
ls -Frt | grep "[^/]$" | tail -n 1
João Fonseca
sumber
1
Ada jawaban lain yang memberikan pertanyaan OP, dan mereka diposting bertahun-tahun yang lalu. Saat mengirim jawaban, pastikan Anda menambahkan solusi baru, atau penjelasan yang jauh lebih baik, terutama saat menjawab pertanyaan yang lebih lama.
help-info.de
2
@ help-info.de Tolong jangan memilih untuk menghapus jawaban yang hanya kode. Mereka mungkin tidak hebat, tetapi penghapusan adalah untuk hal-hal yang bukan jawaban
Machavity
@Machavity - Saya harap tidak gagal dan melakukan komentar hanya untuk jawaban yang terlambat.
help-info.de
0

Jika Anda ingin mendapatkan file yang diubah terbaru juga termasuk subdirektori, Anda dapat melakukannya dengan oneliner kecil ini:

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

Jika Anda ingin melakukan hal yang sama bukan untuk file yang diubah, tetapi untuk file yang diakses Anda harus mengubah

% Y parameter dari Stat perintah untuk % X . Dan perintah Anda untuk sebagian besar file yang diakses terakhir terlihat seperti ini:

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

Untuk kedua perintah, Anda juga dapat mengubah parameter var = "1" jika Anda ingin membuat daftar lebih dari satu file.

OASE Software GmbH
sumber
-1

Saya perlu melakukannya juga, dan saya menemukan perintah-perintah ini. ini bekerja untuk saya:

Jika Anda ingin file terakhir berdasarkan tanggal pembuatannya di folder (waktu akses):

ls -Aru | tail -n 1  

Dan jika Anda ingin file terakhir yang memiliki perubahan dalam kontennya (ubah waktu):

ls -Art | tail -n 1  
masoomeh vahid
sumber