Po prostu przesuń się sort -rprzed forlub wypierz ls -r.
David Schwartz,
Odpowiedzi:
27
W bash lub ksh umieść nazwy plików w tablicy i powtórz tę tablicę w odwrotnej kolejności.
files=(/var/logs/foo*.log)for((i=${#files[@]}-1; i>=0; i--));do
bar "${files[$i]}"done
Powyższy kod działa również w zsh, jeśli ksh_arraysopcja jest ustawiona (działa w trybie emulacji ksh). W zsh istnieje prostsza metoda, polegająca na odwróceniu kolejności dopasowań za pomocą kwalifikatora glob:
for f in/var/logs/foo*.log(On);do bar $f;done
POSIX nie obejmuje tablic, więc jeśli chcesz być przenośny, jedyną opcją do bezpośredniego przechowywania tablicy ciągów są parametry pozycyjne.
set--/var/logs/foo*.log
i=$#while[ $i -gt 0];doeval"f=\${$i}"
bar "$f"
i=$((i-1))done
Kiedy już użyjesz parametrów pozycyjnych, nie potrzebujesz zmiennych ii f; po prostu wykonaj shift, użyj $1do połączenia bari przetestuj [ -z $1 ]w swoim while.
użytkownik1404316,
@ user1404316 Byłby to zbyt skomplikowany sposób iteracji elementów w porządku rosnącym . Również źle: ani [ -z $1 ]nie [ -z "$1" ]są użytecznymi testami (co jeśli parametr był *lub pusty ciąg?). W każdym razie nie pomagają tutaj: pytanie brzmi, jak zapętlić w odwrotnej kolejności.
Gilles „SO- przestań być zły”
Pytanie wyraźnie mówi, że iteruje nazwy plików w / var / log, więc można bezpiecznie założyć, że żaden z parametrów nie będzie „*” ani pusty. Naprawdę jednak poprawiam punkt odwrotnej kolejności.
użytkownik1404316,
7
Spróbuj tego, chyba że rozpatrujesz łamanie linii jako „funky znaków”:
ls /var/logs/foo*.log | tac |while read f;do
bar "$f"done
Czy istnieje metoda, która działa z podziałem linii? (Wiem, że to rzadkie, ale przynajmniej dla celów nauki chciałbym wiedzieć, czy można napisać poprawny kod.)
Mehrdad,
Twórczo używaj tac do odwracania przepływu, a jeśli chcesz pozbyć się niechcianych znaków, takich jak łamanie linii, możesz przesłać potokiem do tr -d '\ n'.
Nie mam tac w moim systemie; Nie wiem, czy jest solidny, ale używałem dla x w $ {mylist}; do revv = "$ {x} $ {revv}"; zrobione
arp
@arp To trochę szokujące, ponieważ tacjest częścią jądra GNU. Ale twoje rozwiązanie jest również dobre.
ACK_stoverflow
@ACK_stoverflow Istnieją systemy bez narzędzi użytkownika Linux.
Kusalananda
@Kusalananda Czy mówisz, że tylko Linux używa GNU coreutils? LOL. Nawet zajęty ma tac. Chociaż na podstawie liczby tacbez-odpowiedzi tutaj zgaduję, że może OSX nie ma tac. W takim przypadku użyj wariantu rozwiązania @ arp - i tak łatwiej to zrozumieć.
ACK_stoverflow
@ACK_stoverflow Tak mówię, tak.
Kusalananda
1
find /var/logs/-name 'foo*.log'-print0 | tail -r | xargs -0 bar
Powinien działać tak, jak chcesz (zostało to przetestowane na Mac OS X i mam zastrzeżenie poniżej ...).
Ze strony podręcznika użytkownika dla find:
-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).
Zasadniczo znajdujesz pliki pasujące do łańcucha + glob i kończysz każdy znakiem NUL. Jeśli twoje nazwy plików zawierają znaki nowej linii lub inne dziwne znaki, find powinien sobie z tym poradzić.
tail -r
pobiera standardowe wejście przez potok i odwraca go (zwróć uwagę, że tail -rwypisuje wszystkie dane wejściowe na standardowe wyjście, a nie tylko na 10 ostatnich wierszy, co jest standardowym ustawieniem domyślnym. man tailwięcej informacji).
Następnie przesyłamy to do 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).
Tutaj xargs oczekuje, że argumenty zostaną oddzielone znakiem NUL, który przekazałeś findi odwróciłeś tail.
+1 świetna odpowiedź. Wygląda na to, że Ubuntu nie obsługuje tail -r... czy robię coś złego?
Mehrdad
1
Nie, nie sądzę, że jesteś. Nie mam włączonej maszyny linux, ale szybkie google dla „linux tail man” nie pokazuje jej jako opcji. sunaku wspomniane tacjako alternatywa, więc spróbowałbym tego zamiast tego
tcdyl
Zredagowałem również odpowiedź, aby uwzględnić inną alternatywę
tcdyl,
Ups, zapomniałem dać +1, kiedy powiedziałem +1 :( Gotowe! Przepraszam za haha :)
Mehrdad
4
tail -rjest specyficzny dla OSX i odwraca dane rozdzielane znakami nowej linii, a nie danych rozdzielanych znakiem zerowym. Twoje drugie rozwiązanie w ogóle nie działa (przesyłasz dane wejściowe ls, co nie ma znaczenia); nie ma łatwej poprawki, która sprawiłaby, że działałby niezawodnie.
Gilles „SO- przestań być zły”
1
W twoim przykładzie zapętlasz kilka plików, ale znalazłem to pytanie ze względu na bardziej ogólny tytuł, który może również obejmować zapętlanie tablicy lub odwracanie w oparciu o dowolną liczbę zamówień.
Oto jak to zrobić w Zsh:
Jeśli zapętlasz elementy w tablicy, użyj tej składni ( źródło )
for f in ${(Oa)your_array};do...done
Oodwraca kolejność określoną w następnej fladze; ajest normalną kolejnością tablic.
Jak powiedział @Gilles, Onodwróci kolejność twoich globowanych plików, np my/file/glob/*(On). Z. To dlatego, że Onjest „odwrotną kolejnością nazw ”.
Mac OSX nie obsługuje tacpolecenia. Rozwiązanie @tcdyl działa, gdy wywołujesz pojedyncze polecenie w forpętli. We wszystkich innych przypadkach najprostszym sposobem obejścia tego jest następujący sposób.
To podejście nie obsługuje posiadania nowych linii w nazwach plików. Podstawowym powodem jest to, że tail -rsortuje on dane wejściowe w postaci znaku nowej linii.
for i in`ls -1 [filename pattern] | tail -r`;do[commands here];done
Istnieje jednak sposób na obejście ograniczenia nowej linii. Jeśli wiesz, że twoje nazwy plików nie zawierają określonego znaku (powiedz „=”), możesz użyć, traby zastąpić wszystkie znaki nowej linii, aby stać się tym znakiem, a następnie wykonać sortowanie. Wynik wyglądałby następująco:
Uwaga: w zależności od wersji trmoże nie obsługiwać '\0'postaci. Można to zwykle obejść, zmieniając ustawienia regionalne na C (ale nie pamiętam, jak dokładnie, ponieważ po naprawieniu raz działa teraz na moim komputerze). Jeśli pojawi się komunikat o błędzie i nie możesz znaleźć obejścia, opublikuj go jako komentarz, aby pomóc w rozwiązaniu problemu.
sort -r
przedfor
lub wypierzls -r
.Odpowiedzi:
W bash lub ksh umieść nazwy plików w tablicy i powtórz tę tablicę w odwrotnej kolejności.
Powyższy kod działa również w zsh, jeśli
ksh_arrays
opcja jest ustawiona (działa w trybie emulacji ksh). W zsh istnieje prostsza metoda, polegająca na odwróceniu kolejności dopasowań za pomocą kwalifikatora glob:POSIX nie obejmuje tablic, więc jeśli chcesz być przenośny, jedyną opcją do bezpośredniego przechowywania tablicy ciągów są parametry pozycyjne.
źródło
i
if
; po prostu wykonajshift
, użyj$1
do połączeniabar
i przetestuj[ -z $1 ]
w swoimwhile
.[ -z $1 ]
nie[ -z "$1" ]
są użytecznymi testami (co jeśli parametr był*
lub pusty ciąg?). W każdym razie nie pomagają tutaj: pytanie brzmi, jak zapętlić w odwrotnej kolejności.Spróbuj tego, chyba że rozpatrujesz łamanie linii jako „funky znaków”:
źródło
f
w mojej sytuacji. Ta odpowiedź działa jednak prawie jak zwykły zamiennik zwykłejfor
linii.Jeśli ktoś próbuje wymyślić sposób odwrócenia iteracji po liście ciągów rozdzielanych spacjami, działa to:
źródło
tac
jest częścią jądra GNU. Ale twoje rozwiązanie jest również dobre.tac
. Chociaż na podstawie liczbytac
bez-odpowiedzi tutaj zgaduję, że może OSX nie ma tac. W takim przypadku użyj wariantu rozwiązania @ arp - i tak łatwiej to zrozumieć.Powinien działać tak, jak chcesz (zostało to przetestowane na Mac OS X i mam zastrzeżenie poniżej ...).
Ze strony podręcznika użytkownika dla find:
Zasadniczo znajdujesz pliki pasujące do łańcucha + glob i kończysz każdy znakiem NUL. Jeśli twoje nazwy plików zawierają znaki nowej linii lub inne dziwne znaki, find powinien sobie z tym poradzić.
pobiera standardowe wejście przez potok i odwraca go (zwróć uwagę, że
tail -r
wypisuje wszystkie dane wejściowe na standardowe wyjście, a nie tylko na 10 ostatnich wierszy, co jest standardowym ustawieniem domyślnym.man tail
więcej informacji).Następnie przesyłamy to do
xargs -0
:Tutaj xargs oczekuje, że argumenty zostaną oddzielone znakiem NUL, który przekazałeś
find
i odwróciłeśtail
.Moje zastrzeżenie: przeczytałem, że
tail
nie gra dobrze z ciągami zakończonymi zerem . Działa to dobrze w systemie Mac OS X, ale nie mogę zagwarantować, że tak jest w przypadku wszystkich * nix. Stąpaj ostrożnie.Powinienem również wspomnieć, że GNU Parallel jest często używany jako
xargs
alternatywa. Możesz to również sprawdzić.Być może czegoś mi brakuje, więc inni powinni wejść.
źródło
tail -r
... czy robię coś złego?tac
jako alternatywa, więc spróbowałbym tego zamiast tegotail -r
jest specyficzny dla OSX i odwraca dane rozdzielane znakami nowej linii, a nie danych rozdzielanych znakiem zerowym. Twoje drugie rozwiązanie w ogóle nie działa (przesyłasz dane wejściowels
, co nie ma znaczenia); nie ma łatwej poprawki, która sprawiłaby, że działałby niezawodnie.W twoim przykładzie zapętlasz kilka plików, ale znalazłem to pytanie ze względu na bardziej ogólny tytuł, który może również obejmować zapętlanie tablicy lub odwracanie w oparciu o dowolną liczbę zamówień.
Oto jak to zrobić w Zsh:
Jeśli zapętlasz elementy w tablicy, użyj tej składni ( źródło )
O
odwraca kolejność określoną w następnej fladze;a
jest normalną kolejnością tablic.Jak powiedział @Gilles,
On
odwróci kolejność twoich globowanych plików, npmy/file/glob/*(On)
. Z. To dlatego, żeOn
jest „odwrotną kolejnością nazw ”.Flagi sortowania Zsh:
a
kolejność tablicL
długość plikul
liczba linkówm
Data modyfikacjin
imię^o
odwrotna kolejność (o
normalna kolejność)O
Odwrotna kolejnośćPrzykłady można znaleźć na https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt i http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- to-master-your-z-shell /
źródło
Mac OSX nie obsługuje
tac
polecenia. Rozwiązanie @tcdyl działa, gdy wywołujesz pojedyncze polecenie wfor
pętli. We wszystkich innych przypadkach najprostszym sposobem obejścia tego jest następujący sposób.To podejście nie obsługuje posiadania nowych linii w nazwach plików. Podstawowym powodem jest to, że
tail -r
sortuje on dane wejściowe w postaci znaku nowej linii.Istnieje jednak sposób na obejście ograniczenia nowej linii. Jeśli wiesz, że twoje nazwy plików nie zawierają określonego znaku (powiedz „=”), możesz użyć,
tr
aby zastąpić wszystkie znaki nowej linii, aby stać się tym znakiem, a następnie wykonać sortowanie. Wynik wyglądałby następująco:Uwaga: w zależności od wersji
tr
może nie obsługiwać'\0'
postaci. Można to zwykle obejść, zmieniając ustawienia regionalne na C (ale nie pamiętam, jak dokładnie, ponieważ po naprawieniu raz działa teraz na moim komputerze). Jeśli pojawi się komunikat o błędzie i nie możesz znaleźć obejścia, opublikuj go jako komentarz, aby pomóc w rozwiązaniu problemu.źródło
prostym sposobem jest użycie,
ls -r
jak wspomniano @David Schwartzźródło
Spróbuj tego:
Myślę, że to najprostszy sposób.
źródło
for
pętli w odwrotnej kolejności”.