Perhatikan juga bahwa saya menambahkan tanda kutip di sekitar $MY_DIR. Dengan begitu, perintah tidak akan gagal jika $MY_DIRberisi spasi.
Jika Anda menggunakan shell modern seperti bash, Anda harus menggunakan $( )shell ambil alih-alih backticks. Anda juga harus mempertimbangkan mengubah gaya variabel Anda. Anda umumnya harus menghindari menggunakan nama variabel huruf besar semua dalam skrip. Gaya itu umumnya dicadangkan untuk variabel cadangan dan lingkungan.
input_file=$(ls -rt "$my_dir"/FILE.*.xml 2>/dev/null | head -1| xargs -r basename)
Sebenarnya: ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basenameberfungsi.
Mel Boyce
@MelBoyce: Saya telah menambahkan itu ke jawaban saya. Terima kasih.
ls adalah alat untuk melihat informasi file secara interaktif. Outputnya diformat untuk manusia dan akan menyebabkan bug pada skrip. Gunakan gumpalan atau temukan sebagai gantinya. Pahami mengapa: mywiki.wooledge.org/ParsingLs
cinelli
@cinelli: Itu benar. Saya hanya menjawab pertanyaan itu.
9
Dalam saluran pipa, semua perintah dimulai dan dijalankan secara bersamaan, bukan satu demi satu. Jadi, Anda perlu menyimpan output di suatu tempat.
if ls_output=$(ls -rtd --"$MY_DIR"/FILE.*.xml);then
first_file=$(printf '%s\n'"$ls_output"| head -n 1)
first_file_name=$(basename --"$first_file")fi
Perhatikan bahwa ini mengasumsikan nama file tidak mengandung karakter baris baru. Menggunakan xargsjuga berarti masalah dengan karakter kosong, tanda kutip tunggal dan ganda dan garis miring terbalik. Meninggalkan variabel yang tidak dikutip akan berarti masalah dengan karakter spasi, tab dan karakter pengganti. Lupa --berarti masalah dengan nama file yang dimulai dengan -.
Untuk mendapatkan nama file dari file terlama dengan zshtanpa batasan karakter apa pun (juga menghindari masalah ukuran argumen terbatas pada perintah):
first_file_name=($MY_DIR/FILE.*.xml(Om[1]:t))
Jika tidak ada kecocokan, perintah itu akan gagal dan membatalkan skrip. Anda juga dapat melakukan:
first_file_name=($MY_DIR/FILE.*.xml(NOm[1]:t))
Dalam hal ini first_file_namearray akan berisi 1 elemen jika ada kecocokan atau 0 jika tidak. Anda kemudian dapat melakukan:
if(($#first_file_name)); then
printf 'Match: %s\n' $first_file_name
else
echo >&2No match
fi
Untuk menggunakan ini dengan benar untuk memenuhi tujuan permintaan Anda:
check_dir=/path/to/check
check_ext=.xml
if in_file=$(latest "$check_dir""$check_ext");then
base_fn=${in_file##*/} base_fn=${base_fn%.*}else
printf '%s\n'"No file found in $check_dir">&2fi
EDIT: setelah meninjau pertanyaan, saya menyadari bahwa lsperintah tersebut mencari file tertua di direktori. fungsi yang sama ini dapat diubah namanya menjadi oldestdan memiliki [[ $file -ot $oldest ]] && oldest=$fileuntuk mencapai efek yang sama. permintaan maaf untuk kebingungan
hal penting yang perlu diperhatikan adalah bahwa Anda benar-benar, dalam keadaan apa pun dalam umat manusia, tidak boleh mem-parsing keluaran ls. tidak pernah.
Perhatikan bahwa bertentangan dengan lspendekatan berbasis, jika ada symlink, waktu modifikasi target symlink akan dipertimbangkan (tambahkan -Lopsi lsuntuk mendapatkan perilaku yang sama di sana).
Alih-alih membandingkan $?terhadap 0, Anda dapat melakukan ini: if ls -rf $MY_DIR/FILE.*.xml ; then.
Anda juga dapat mengarahkan output dari perintah pertama ke /dev/null. ls -rf $MY_DIR/FILE.*.xml &> /dev/null. Dengan begitu, pengguna tidak akan melihat output tambahan.
ls
tidak akan gagal.Jawaban:
Coba ini:
Melewati
xargs
satu-r
bendera akan menyebabkan ia hanya menjalankanbasename
jika membaca setidaknya satu item dari input standar (head -1
).head -1
akan berjalan tetapi Anda tidak akan melihat atau menangkap output apa pun darinya.Juga, jika Anda tidak ingin pengguna melihat output kesalahan
ls
, Anda dapat mengarahkan ulangls
aliran stderr ke/dev/null
.Perhatikan juga bahwa saya menambahkan tanda kutip di sekitar
$MY_DIR
. Dengan begitu, perintah tidak akan gagal jika$MY_DIR
berisi spasi.Jika Anda menggunakan shell modern seperti bash, Anda harus menggunakan
$( )
shell ambil alih-alih backticks. Anda juga harus mempertimbangkan mengubah gaya variabel Anda. Anda umumnya harus menghindari menggunakan nama variabel huruf besar semua dalam skrip. Gaya itu umumnya dicadangkan untuk variabel cadangan dan lingkungan.sumber
ls -rt GLOB 2>/dev/null | head -n1 | xargs -r basename
berfungsi.Dalam saluran pipa, semua perintah dimulai dan dijalankan secara bersamaan, bukan satu demi satu. Jadi, Anda perlu menyimpan output di suatu tempat.
Perhatikan bahwa ini mengasumsikan nama file tidak mengandung karakter baris baru. Menggunakan
xargs
juga berarti masalah dengan karakter kosong, tanda kutip tunggal dan ganda dan garis miring terbalik. Meninggalkan variabel yang tidak dikutip akan berarti masalah dengan karakter spasi, tab dan karakter pengganti. Lupa--
berarti masalah dengan nama file yang dimulai dengan-
.Untuk mendapatkan nama file dari file terlama dengan
zsh
tanpa batasan karakter apa pun (juga menghindari masalah ukuran argumen terbatas pada perintah):Jika tidak ada kecocokan, perintah itu akan gagal dan membatalkan skrip. Anda juga dapat melakukan:
Dalam hal ini
first_file_name
array akan berisi 1 elemen jika ada kecocokan atau 0 jika tidak. Anda kemudian dapat melakukan:sumber
Temukan file yang dimodifikasi terbaru dalam direktori:
Pemakaian:
latest [directory/path/ [.extension]]
Alih-alih memanggil
basename
, gunakan ekspansi parameter.Dalam direktori dengan konten ini:
Isi variabel base_fn adalah:
newest
Untuk menggunakan ini dengan benar untuk memenuhi tujuan permintaan Anda:
EDIT: setelah meninjau pertanyaan, saya menyadari bahwa
ls
perintah tersebut mencari file tertua di direktori. fungsi yang sama ini dapat diubah namanya menjadioldest
dan memiliki[[ $file -ot $oldest ]] && oldest=$file
untuk mencapai efek yang sama. permintaan maaf untuk kebingunganhal penting yang perlu diperhatikan adalah bahwa Anda benar-benar, dalam keadaan apa pun dalam umat manusia, tidak boleh mem-parsing keluaran ls. tidak pernah.
sumber
ls
pendekatan berbasis, jika ada symlink, waktu modifikasi target symlink akan dipertimbangkan (tambahkan-L
opsils
untuk mendapatkan perilaku yang sama di sana).Saya pikir pilihan terbaik di sini adalah:
jika tidak ada file maka kode pengembalian ls adalah 2 tetapi jika menemukan beberapa file akan menjadi 0.
sumber
$?
terhadap0
, Anda dapat melakukan ini:if ls -rf $MY_DIR/FILE.*.xml ; then
./dev/null
.ls -rf $MY_DIR/FILE.*.xml &> /dev/null
. Dengan begitu, pengguna tidak akan melihat output tambahan.