Hanya pipa sort -rsebelum for, atau mencuci melalui ls -r.
David Schwartz
Jawaban:
27
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_arraysopsi 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];doeval"f=\${$i}"
bar "$f"
i=$((i-1))done
Setelah Anda menggunakan parameter posisi, tidak perlu untuk variabel Anda idan f; hanya melakukan shift, gunakan $1untuk panggilan Anda bar, dan uji pada [ -z $1 ]Anda while.
user1404316
@ user1404316 Ini akan menjadi cara yang terlalu rumit untuk mengulangi elemen-elemen dalam urutan menaik . Juga, salah: tidak [ -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.
Gilles 'SO- stop being evil'
Pertanyaannya secara spesifik mengatakan bahwa itu adalah iterasi dari nama file di / var / log, jadi aman untuk mengasumsikan bahwa tidak ada parameter yang menjadi "*" atau kosong. Saya berdiri dikoreksi, pada titik urutan terbalik.
user1404316
7
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
Apakah ada metode yang bekerja dengan jeda baris? (Saya tahu ini jarang terjadi, tetapi setidaknya untuk belajar saya ingin tahu apakah mungkin untuk menulis kode yang benar.)
Mehrdad
Materi iklan menggunakan tac untuk membalikkan alur, dan jika Anda ingin menghilangkan beberapa karakter yang tidak diinginkan seperti jeda baris, Anda dapat melakukan pipe ke tr -d '\ n'.
Jawaban yang paling banyak memberikan suara memecahkan variabel fdalam situasi saya. Namun jawaban ini, bertindak cukup banyak sebagai pengganti drop-in untuk forgaris biasa .
Serge Stroobandt
2
Jika ada yang mencoba mencari cara untuk membalikkan iterate pada daftar string yang dibatasi ruang, ini berfungsi:
Saya tidak punya tac di sistem saya; Saya tidak tahu apakah itu kuat tetapi saya telah menggunakan untuk x dalam $ {daftar saya}; do revv = "$ {x} $ {revv}"; selesai
arp
@arp Itu agak mengejutkan karena tacmerupakan bagian dari GNU coreutils. Tapi solusi Anda juga bagus.
ACK_stoverflow
@ACK_stoverflow Ada sistem di luar sana tanpa alat pengguna Linux.
Kusalananda
@ Kusalananda Apakah Anda mengatakan bahwa hanya Linux yang menggunakan GNU coreutils? LOL. Bahkan busybox punya 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.
ACK_stoverflow
@ACK_stoverflow Itulah yang saya katakan, ya.
Kusalananda
1
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 -rmencetak semua input ke stdout, dan bukan hanya 10 baris terakhir, yang merupakan standar standar. man tailuntuk info lebih lanjut).
Kami kemudian mengirimkannya ke xargs -0:
-0Change xargs to expect NUL (``\0'') characters as separators, instead of spaces and newlines.This is expected to be used in concert with the
-print0 functionin find(1).
Di sini, xargs mengharapkan untuk melihat argumen yang dipisahkan oleh karakter NUL, yang Anda berikan finddan balikkan tail.
+1 jawaban yang bagus. Sepertinya Ubuntu tidak mendukung tail -r... apakah saya melakukan sesuatu yang salah?
Mehrdad
1
Tidak, kurasa tidak. Saya tidak memiliki mesin linux saya tetapi google cepat untuk 'linux tail man' tidak menunjukkannya sebagai opsi. sunaku disebut tacsebagai alternatif, jadi saya akan mencobanya, sebagai gantinya
tcdyl
Saya juga mengedit jawaban untuk menyertakan alternatif lain
tcdyl
whoops Saya lupa memberi +1 ketika saya berkata +1 :( Selesai! Maaf soal itu haha :)
Mehrdad
4
tail -rkhusus 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.
Gilles 'SO- stop being evil'
1
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
Omembalikkan urutan yang ditentukan dalam bendera berikutnya; aadalah susunan array normal.
Seperti yang dikatakan @Gilles, Onakan membalik urutan file globbed Anda, misalnya dengan my/file/glob/*(On). Itu karena On" urutan nama terbalik ."
Mac OSX tidak mendukung tacperintah. Solusi oleh @tcdyl bekerja ketika Anda memanggil satu perintah dalam satu forlingkaran. 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 -rmemilah 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 truntuk mengganti semua baris baru untuk menjadi karakter ini, dan kemudian melakukan pengurutan. Hasilnya akan terlihat sebagai berikut:
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
.Jawaban:
Dalam bash atau ksh, letakkan nama file dalam array, dan ulangi array itu dalam urutan terbalik.
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:POSIX tidak termasuk array, jadi jika Anda ingin portabel, satu-satunya pilihan Anda untuk langsung menyimpan array string adalah parameter posisi.
sumber
i
danf
; hanya melakukanshift
, gunakan$1
untuk panggilan Andabar
, dan uji pada[ -z $1 ]
Andawhile
.[ -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":
sumber
f
dalam situasi saya. Namun jawaban ini, bertindak cukup banyak sebagai pengganti drop-in untukfor
garis biasa .Jika ada yang mencoba mencari cara untuk membalikkan iterate pada daftar string yang dibatasi ruang, ini berfungsi:
sumber
tac
merupakan bagian dari GNU coreutils. Tapi solusi Anda juga bagus.tac
. Meskipun dari jumlahtac
-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.Harus beroperasi seperti yang Anda inginkan (ini diuji pada Mac OS X dan saya memiliki peringatan di bawah ...).
Dari halaman manual untuk menemukan:
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.
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
:Di sini, xargs mengharapkan untuk melihat argumen yang dipisahkan oleh karakter NUL, yang Anda berikan
find
dan balikkantail
.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.
sumber
tail -r
... apakah saya melakukan sesuatu yang salah?tac
sebagai alternatif, jadi saya akan mencobanya, sebagai gantinyatail -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 kels
, 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 )
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 denganmy/file/glob/*(On)
. Itu karenaOn
" 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 /
sumber
Mac OSX tidak mendukung
tac
perintah. Solusi oleh @tcdyl bekerja ketika Anda memanggil satu perintah dalam satufor
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.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: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.sumber
cara mudah adalah menggunakan
ls -r
seperti yang disebutkan oleh @ David Schwartzsumber
Coba ini:
Saya pikir ini adalah cara yang paling sederhana.
sumber
for
loop dalam urutan terbalik”.