Yanıtlar:
Bash veya ksh'da dosya adlarını bir diziye yerleştirin ve bu dizinin tersini sırayla yineleyin.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
Eğer ksh_arraysseçenek ayarlanmışsa yukarıdaki kod da zsh ile çalışır (ksh emülasyon modundadır). Zsh'da daha basit bir yöntem vardır, ki bu da maçların sırasını bir glob elemesinden geriye çevirir:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX, dizileri içermez; bu nedenle, taşınabilir olmak istiyorsanız, bir dizi diziyi doğrudan saklamak için tek seçeneğiniz konumsal parametrelerdir.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
ive f; Sadece bir gerçekleştirin shift, $1görüşmeniz için kullanın ve kendi içinde bartest [ -z $1 ]edin while.
[ -z $1 ]de [ -z "$1" ]yararlı testlerdir (parametre ne olursa *veya boş bir dize?). Ve her durumda burada yardımcı olmuyorlar: soru, ters sırada nasıl döngü oluşturulacağıdır.
Satır sonlarını "funky karakter" olarak düşünmüyorsanız, bunu deneyin:
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
fdurumumdaki değişkeni kırdı . Bu cevap olsa da, sıradan forhat için bir açılan yerine hemen hemen hareket eder .
Herhangi biri, boşlukla ayrılmış bir dize listesi üzerinde yinelemenin nasıl tersine çevrileceğini anlamaya çalışıyorsa, bu işe yarar:
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
tacGNU coreutils'in bir parçası olarak bu bir tür şok edici . Ancak çözümünüz de iyi bir çözümdür.
tac. tacBuradaki cevapsız cevap sayısından rağmen, belki OSX'in taclı olmadığını tahmin ediyorum. Bu durumda @ arp'ın çözümünün bir türünü kullanın - yine de anlamak daha kolaydır.
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
İstediğiniz şekilde çalışması gerekir (bu Mac OS X'te test edildi ve aşağıda bir uyarı var).
Bulmak için man sayfasından:
-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).
Temel olarak, string + glob'unuzla eşleşen dosyaları buluyorsunuz ve her birini NUL karakteriyle sonlandırıyorsunuz. Dosya adlarınız yeni satırlar veya başka garip karakterler içeriyorsa, bu işlemi iyi yapmalı.
tail -r
borudan standart girdi alır ve onu tersine çevirir (not bu tail -rbaskılar tüm standart varsayılan olan Stdout'a girdi ve sadece son 10 satır. man taildaha fazla bilgi için).
Daha sonra bu borulara 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).
Burada xargs, içinden geçtiğin findve tersine döndüğü NUL karakteriyle ayrılmış argümanları görmeyi bekler tail.
Notum: Boş sonlandırılmış dizelerle iyi sonuçlanmadığını okudumtail . Bu, Mac OS X'te iyi çalıştı, ancak tüm * nix'ler için geçerli olduğunu garanti edemiyorum. Dikkatlice basmak.
Ayrıca GNU Parallel'in sıklıkla xargsalternatif olarak kullanıldığını da belirtmeliyim . Bunu da kontrol edebilirsiniz.
Bir şeyleri özlüyorum, o yüzden başkaları içeri girmeli.
tail -ryine de desteklemiyor ... yanlış bir şey mi yapıyorum?
tacalternatif olarak bahsetti , bu yüzden bunu denerdim
tail -rOSX’e özgüdür ve yeni satırla sınırlandırılmış girişi ters çevirir, sıfırdan ayrılmış girişi değil. İkinci çözümünüz hiç işe yaramıyor (girişini lsumursuyorsunuz, hangisi umursamıyor); güvenilir çalışmasını sağlayacak kolay bir düzeltme yoktur.
Örneğinizde, birkaç dosya üzerinden geçiyorsunuz, ancak bu soruyu bir dizinin üzerinden çevrilmeyi de kapsayabilecek daha genel başlığı nedeniyle veya herhangi bir sayıdaki emri temel alarak değiştirebildiğim için buldum.
İşte Zsh'da bunun nasıl yapılacağı:
Bir dizideki öğeler üzerinde dolaşıyorsanız, bu sözdizimini ( kaynak ) kullanın.
for f in ${(Oa)your_array}; do
...
done
Obir sonraki bayrakta belirtilen emrin tersi; anormal dizi sırasıdır.
@Gilles’in dediği gibi globbed Ondosyalarınızı tersine çevirir my/file/glob/*(On). Çünkü On"ters isim sırası " dır .
Zsh sıralama bayrakları:
a dizi sırasıL dosya uzunluğul bağlantı sayısım düzenleme tarihin isim^oTers sıra ( onormal sıra)O Ters siparişÖrnekler için bkz. Https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt ve http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- -ana-daki-z-kabuk /
Mac OSX tackomutu desteklemiyor . @Tcdyl çözümü bir fordöngüde tek bir komut çağırdığınızda çalışır . Diğer tüm durumlar için, aşmanın en basit yolu aşağıdaki gibidir.
Bu yaklaşım, dosya adlarınızda yeni satırlara sahip olmayı desteklemiyor. Bunun temel nedeni, tail -rgirişini yeni satırlarla sınırlandırılmış şekilde sıralamasıdır.
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
Ancak, newline sınırlamasını aşmanın bir yolu var. Dosya adlarınızın belirli bir karakter içermediğini biliyorsanız ('=' deyin), o zaman trtüm yeni satırları bu karakter haline getirmek için kullanabilir ve ardından sıralamayı yapabilirsiniz. Sonuç şöyle görünür:
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
Not: Sürümünüze bağlı olarak, karakter olarak trdesteklemeyebilir '\0'. Bu genellikle yerel ayarları C olarak değiştirerek işe yarar (ancak bilgisayarımda bir kez düzelttikten sonra tam olarak nasıl olduğunu tam olarak hatırlamıyorum). Bir hata mesajı alırsanız ve geçici çözümü bulamazsanız, lütfen yorum olarak gönderin, sorun gidermenize yardımcı olabilirim.
sort -rönce borufor, ya da üzerinden aklamals -r.