Bisakah saya memilih hanya satu hasil dari bash glob?


14

Saya mencoba menulis skrip untuk pekerjaan untuk mengotomatiskan beberapa pelaporan pada output. File-file Log (saat ini sedang 'dibakukan' di masa depan) disimpan dalam struktur jalur semacam ini:

/<root_path>/<process_one_path>/logs/<time_date_stamp>/<specific_log_file>

/<root_path>/<process_two_path>/logs/<different_time_date_stamp>/<specific_log_file>

Setiap bagian dari jalur diketahui kecuali cap tanggal waktu, yang selalu merupakan yang terbaru di folder.

Jika saya mencoba menggunakan kartu liar sebagai ganti cap tanggal waktu, saya mendapatkan beberapa hasil, misalnya:

> ls /<root_path>/<process_two_path>/logs/* [tab]
20130102-175103
20130118-090859
20130305-213506

Saya hanya ingin mengembalikan yang terbaru, apakah ini mungkin dengan Bash?

NB (Saya tidak punya zsh, dan sebagus kedengarannya saya ragu kita akan mendapatkannya di tempat kerja)

Jawaban:


9

Karya-karya berikut di bash 4.2:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[-1]}"

Jika bash Anda adalah versi yang lebih lama:

list=( /<root_path>/<process_two_path>/logs/* )
echo "${list[${#list[@]}-1]}"

Ini pasti bekerja di komputer rumah saya, tetapi saya tidak dapat menjamin itu akan berfungsi di tempat kerja?
Pureferret

@ Pureferret bagian yang mungkin tidak berfungsi adalah indeks array negatif ( -1). Ini ditambahkan di bash 4.2. RHEL5 mungkin adalah distro perusahaan utama tertua yang didukung yang tersedia dan menggunakan bash 4.2.20.
Patrick

1
Versi lama bashhave: "${list[@]: -1}"like in ksh93( [-1]berasal dari zsh).
Stéphane Chazelas

@Patrick - RHEL5 menggunakan bash 3.2. RHEL 3 dan 4 masih didukung dalam usia yang panjang.
jordanm

1
@ Pureferret Anda juga dapat melakukan aritmatika dengan panjang array, lihat hasil edit saya.
Gilles 'SO- berhenti menjadi jahat'

10

POSIXly:

 set -- /<root_path>/<process_two_path>/logs/*
 shift "$(($# - 1))"
 printf '%s\n' "$1"

Karena Anda menyebutkan zsh:

 print -r /<root_path>/<process_two_path>/logs/*([-1])

4

Gunakan bash glob di bash untuk loop. Seperti ini:

for filename in <logdir>/*; do :; done; echo "$filename"

Ini tergantung pada fakta bahwa bash melakukan ekspansi glob yang diurutkan berdasarkan abjad. Baca manual bash untuk informasi lebih lanjut. Perhatikan bahwa ini tergantung pada LC_COLLATE . Ini juga tergantung pada fakta bahwa variabel filenamemasih berisi nilai terakhir setelah loop telah diakhiri.

Jika Anda ingin nama file dengan cap waktu tertua, Anda dapat melakukannya seperti ini:

for filename in <logdir>/*; do echo "$filename"; break; done

1

-1 adalah default dalam pipa, dan ls output harus sudah diurutkan:

ls | tail -n1

Jika orang lain mencari cara memasukkan hasil pertama atau terakhir secara interaktif, Anda dapat mengikat menu-complete atau menu-complete-backward di .inputrc:

"\e\t": menu-complete
"\e[Z": menu-complete-backward # shift-tab

Jika show-all-if-ambiguous diaktifkan, set completion-query-items 0hapus prompt ketika ada 101 atau lebih hasil dan set page-completions offmenonaktifkan pager.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.