Di Bash, saya ingin membuat fungsi yang mengembalikan nama file dari file terbaru yang cocok dengan pola tertentu. Sebagai contoh, saya memiliki direktori file seperti:
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
Saya ingin file terbaru yang dimulai dengan 'b2'. Bagaimana saya melakukan ini di bash? Saya perlu memiliki ini di ~/.bash_profile
skrip saya .
Jawaban:
The
ls
perintah memiliki parameter-t
untuk mengurutkan berdasarkan waktu. Anda kemudian dapat mengambil yang pertama (terbaru) denganhead -1
.Tetapi waspadalah: Mengapa Anda tidak harus menguraikan output ls
Pendapat pribadi saya: parsing
ls
hanya berbahaya ketika nama file dapat berisi karakter lucu seperti spasi atau baris baru. Jika Anda dapat menjamin bahwa nama file tidak akan mengandung karakter lucu maka parsingls
cukup aman.Jika Anda sedang mengembangkan skrip yang dimaksudkan untuk dijalankan oleh banyak orang pada banyak sistem dalam banyak situasi yang berbeda maka saya sangat merekomendasikan untuk tidak melakukan parse
ls
.Berikut ini cara melakukannya "benar": Bagaimana saya dapat menemukan file terbaru (terbaru, paling awal, terlama) dalam direktori?
sumber
ls
,printf "%s\n" b2* | head -1
akan melakukannya untuk Anda.b2.10_5_2
membunuh solusi ini.Kombinasi
find
danls
berfungsi dengan baik untukSolusinya:
Mari kita jabarkan:
Dengan
find
kita dapat mencocokkan semua file menarik seperti ini:lalu menggunakan
-print0
kita bisa memberikan semua nama file dengan aman ke yangls
seperti ini:find
parameter dan pola pencarian tambahan dapat ditambahkan di sinils -t
akan mengurutkan file berdasarkan waktu modifikasi (terbaru terlebih dahulu) dan mencetaknya satu per satu. Anda dapat menggunakannya-c
untuk mengurutkan berdasarkan waktu pembuatan. Catatan : ini akan pecah dengan nama file yang mengandung baris baru.Akhirnya
head -1
memberi kami file pertama dalam daftar diurutkan.Catatan:
xargs
gunakan batas sistem untuk ukuran daftar argumen. Jika ukuran ini melebihi,xargs
akan memanggills
beberapa kali. Ini akan mematahkan penyortiran dan mungkin juga hasil akhir. Lariuntuk memeriksa batas pada sistem Anda.
Catatan 2: gunakan
find . -maxdepth 1 -name "my-pattern" -print0
jika Anda tidak ingin mencari file melalui subfolder.Catatan 3: Seperti yang ditunjukkan oleh @starfry -
-r
argumen untukxargs
mencegah panggilanls -1 -t
, jika tidak ada file yang cocok denganfind
. Terima kasih atas sarannya.sumber
find . -name "my-pattern" ... -print0
memberi sayafind: paths must precede expression: `...'
...
singkatan dari "lebih banyak parameter". Abaikan saja, jika Anda tidak membutuhkannya.-r
baris perintah xargs yang memberi tahu xargs untuk tidak menjalankan baris perintahnya jika tidak menerima apa pun pada input standarnya.-r
jawaban.Ini adalah implementasi yang mungkin dari fungsi Bash yang diperlukan:
Hanya menggunakan Bash bawaan, dan harus menangani file yang namanya berisi baris baru atau karakter tidak biasa lainnya.
sumber
nullglob_shopt=$(shopt -p nullglob)
dan kemudian$nullglob
untuk mengembalikannullglob
bagaimana sebelumnya.$()
atau backticks) karena lambat, terutama di bawah Cygwin, bahkan ketika perintah hanya menggunakan builtin. Juga, konteks subkulit di mana perintah dijalankan kadang-kadang dapat menyebabkan mereka berperilaku dengan cara yang tidak terduga. Saya juga mencoba untuk menghindari menyimpan perintah dalam variabel (sepertinullglob_shopt
) karena hal-hal yang sangat buruk dapat terjadi jika Anda mendapatkan nilai dari variabel yang salah.cat
!'. Bahkan jika ini membutuhkan lebih banyak kerja, ia memiliki manfaat menunjukkan konsep orang. Punya +1!Nama file yang tidak biasa (seperti file yang berisi
\n
karakter yang valid dapat mendatangkan malapetaka dengan parsing semacam ini. Berikut cara untuk melakukannya di Perl:Itu transformasi Schwartzian yang digunakan di sana.
sumber
Anda dapat menggunakan
stat
glob file dan menghias-sort-undecorate dengan waktu file yang ditambahkan di bagian depan:sumber
stat
, jika saya mengingat opsinya dengan benar. Untuk mendapatkan hasil serupa di platform lain, Anda bisa menggunakanstat -c $'%Y\t%n' b2* | sort -rn | head -n1 | cut -f2-
Mantra fungsi ilmu hitam bagi mereka yang menginginkan
find ... xargs ... head ...
solusi di atas, tetapi dalam bentuk fungsi yang mudah digunakan sehingga Anda tidak perlu berpikir:Cetakan:
Yang mana:
Nama file dengan stempel waktu modifikasi tertua dari file di bawah direktori yang diberikan cocok dengan pola yang diberikan.
sumber
Gunakan perintah find.
Dengan asumsi Anda menggunakan Bash 4.2+, gunakan
-printf '%T+ %p\n'
untuk nilai cap waktu file.Contoh:
Untuk skrip yang lebih bermanfaat, lihat skrip temukan-terbaru di sini: https://github.com/l3x/helpers
sumber
Ada cara yang jauh lebih efisien untuk mencapai ini. Pertimbangkan perintah berikut:
Perintah ini menemukan file terbaru yang diproduksi tepat satu menit yang lalu dengan pencarian wildcard pada "b2 *". Jika Anda ingin file dari dua hari terakhir maka Anda akan lebih baik menggunakan perintah di bawah ini:
"." mewakili direktori saat ini. Semoga ini membantu.
sumber