Jawaban:
Dalam bash atau ksh, letakkan nama file dalam array, dan ulangi array itu dalam urutan terbalik.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
Kode di atas juga berfungsi di zsh jika ksh_arrays
opsi diset (ini dalam mode emulasi ksh). Ada metode yang lebih sederhana di zsh, yaitu membalik urutan pertandingan melalui kualifikasi glob:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX tidak termasuk array, jadi jika Anda ingin portabel, satu-satunya pilihan Anda untuk langsung menyimpan array string adalah parameter posisi.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
i
dan f
; hanya melakukan shift
, gunakan $1
untuk panggilan Anda bar
, dan uji pada [ -z $1 ]
Anda while
.
[ -z $1 ]
atau [ -z "$1" ]
tes yang berguna (bagaimana jika parameter itu *
, atau string kosong?). Dan dalam kasus apa pun mereka tidak membantu di sini: pertanyaannya adalah bagaimana mengulang dalam urutan yang berlawanan.
Coba ini, kecuali jika Anda menganggap jeda baris sebagai "karakter yang funky":
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
f
dalam situasi saya. Namun jawaban ini, bertindak cukup banyak sebagai pengganti drop-in untuk for
garis biasa .
Jika ada yang mencoba mencari cara untuk membalikkan iterate pada daftar string yang dibatasi ruang, ini berfungsi:
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
tac
merupakan bagian dari GNU coreutils. Tapi solusi Anda juga bagus.
tac
. Meskipun dari jumlah tac
-penghasilan tanggapan di sini saya kira mungkin OSX tidak memiliki tac. Dalam hal ini gunakan beberapa varian solusi @ arp - bagaimanapun juga lebih mudah untuk dipahami.
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
Harus beroperasi seperti yang Anda inginkan (ini diuji pada Mac OS X dan saya memiliki peringatan di bawah ...).
Dari halaman manual untuk menemukan:
-print0
This primary always evaluates to true. It prints the pathname of the current file to standard output, followed by an ASCII NUL character (charac-
ter code 0).
Pada dasarnya, Anda menemukan file yang cocok dengan string + glob Anda dan mengakhiri masing-masing dengan karakter NUL. Jika nama file Anda mengandung baris baru atau karakter aneh lainnya, find harus menangani ini dengan baik.
tail -r
mengambil input standar melalui pipa dan membalikkannya (perhatikan bahwa tail -r
mencetak semua input ke stdout, dan bukan hanya 10 baris terakhir, yang merupakan standar standar. man tail
untuk info lebih lanjut).
Kami kemudian mengirimkannya ke xargs -0
:
-0 Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines. This is expected to be used in concert with the
-print0 function in find(1).
Di sini, xargs mengharapkan untuk melihat argumen yang dipisahkan oleh karakter NUL, yang Anda berikan find
dan balikkan tail
.
Peringatan saya: Saya pernah baca yang tail
tidak cocok dengan string yang diakhiri null . Ini bekerja dengan baik pada Mac OS X, tetapi saya tidak dapat menjamin bahwa ini berlaku untuk semua * nixes. Tapak dengan hati-hati.
Saya juga harus menyebutkan bahwa GNU Parallel sering digunakan sebagai xargs
alternatif. Anda dapat memeriksanya juga.
Saya mungkin kehilangan sesuatu, jadi orang lain harus berpadu.
tail -r
... apakah saya melakukan sesuatu yang salah?
tac
sebagai alternatif, jadi saya akan mencobanya, sebagai gantinya
tail -r
khusus untuk OSX, dan membalikkan input yang dibatasi-baris, bukan input yang dibatasi-nol. Solusi kedua Anda tidak bekerja sama sekali (Anda memasukkan masukan ke ls
, yang tidak peduli); tidak ada perbaikan mudah yang akan membuatnya bekerja dengan andal.
Dalam contoh Anda, Anda mengulang-ulang beberapa file, tetapi saya menemukan pertanyaan ini karena judulnya yang lebih umum yang juga dapat mencakup pengulangan pada array, atau membalikkan berdasarkan jumlah pesanan.
Berikut cara melakukannya di Zsh:
Jika Anda mengulang elemen di dalam array, gunakan sintaks ini ( sumber )
for f in ${(Oa)your_array}; do
...
done
O
membalikkan urutan yang ditentukan dalam bendera berikutnya; a
adalah susunan array normal.
Seperti yang dikatakan @Gilles, On
akan membalik urutan file globbed Anda, misalnya dengan my/file/glob/*(On)
. Itu karena On
" urutan nama terbalik ."
Zsh sort flags:
a
urutan arrayL
panjang filel
jumlah tautanm
tanggal modifikasin
nama^o
urutan terbalik ( o
adalah urutan normal)O
urutan terbalikSebagai contoh, lihat https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt dan http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- to-master-your-z-shell /
Mac OSX tidak mendukung tac
perintah. Solusi oleh @tcdyl bekerja ketika Anda memanggil satu perintah dalam satu for
lingkaran. Untuk semua kasus lain, berikut ini adalah cara paling sederhana untuk menyiasatinya.
Pendekatan ini tidak mendukung memiliki baris baru di nama file Anda. Alasan yang mendasari adalah, yang tail -r
memilah inputnya seperti dibatasi oleh baris baru.
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
Namun, ada cara untuk mengatasi batasan baris baru. Jika Anda tahu nama file Anda tidak mengandung karakter tertentu (katakanlah, '='), maka Anda dapat menggunakan tr
untuk mengganti semua baris baru untuk menjadi karakter ini, dan kemudian melakukan pengurutan. Hasilnya akan terlihat sebagai berikut:
for i in `find [directory] -name '[filename]' -print0 | tr '\n' '=' | tr '\0' '\n'
| tail -r | tr '\n' '\0' | tr '=' '\n' | xargs -0`; do [commands]; done
Catatan: tergantung pada versi Anda tr
, itu mungkin tidak mendukung '\0'
sebagai karakter. Ini biasanya dapat dikerjakan dengan mengubah lokal ke C (tapi saya tidak ingat bagaimana tepatnya, karena setelah memperbaikinya sekarang berfungsi di komputer saya). Jika Anda mendapatkan pesan kesalahan, dan Anda tidak dapat menemukan solusinya, silakan kirimkan sebagai komentar, jadi saya dapat membantu Anda memecahkan masalah itu.
sort -r
sebelumfor
, atau mencuci melaluils -r
.