Antworten:
Fügen Sie in bash oder ksh die Dateinamen in ein Array ein und durchlaufen Sie das Array in umgekehrter Reihenfolge.
files=(/var/logs/foo*.log)
for ((i=${#files[@]}-1; i>=0; i--)); do
bar "${files[$i]}"
done
Der obige Code funktioniert auch in zsh, wenn die ksh_arrays
Option gesetzt ist (im ksh-Emulationsmodus). Es gibt eine einfachere Methode in zsh, die darin besteht, die Reihenfolge der Übereinstimmungen durch ein Glob-Qualifikationsmerkmal umzukehren:
for f in /var/logs/foo*.log(On); do bar $f; done
POSIX enthält keine Arrays. Wenn Sie also portabel sein möchten, können Sie nur die Positionsparameter verwenden, um ein Array von Strings direkt zu speichern.
set -- /var/logs/foo*.log
i=$#
while [ $i -gt 0 ]; do
eval "f=\${$i}"
bar "$f"
i=$((i-1))
done
i
und nicht mehr erforderlich f
. führen Sie einfach ein shift
, verwenden Sie es $1
für Ihren Anruf bar
und testen Sie es [ -z $1 ]
in Ihrem while
.
[ -z $1 ]
noch [ -z "$1" ]
nützliche Tests (was, wenn der Parameter war *
, oder eine leere Zeichenfolge?). Und auf jeden Fall helfen sie hier nicht weiter: Die Frage ist, wie in umgekehrter Reihenfolge geschleift werden soll.
Versuchen Sie dies, es sei denn, Sie betrachten Zeilenumbrüche als "flippige Zeichen":
ls /var/logs/foo*.log | tac | while read f; do
bar "$f"
done
f
in meiner Situation gebrochen . Diese Antwort fungiert jedoch als Ersatz für die normale for
Leitung.
Wenn jemand versucht, herauszufinden, wie er über eine durch Leerzeichen getrennte Zeichenfolgenliste iterieren kann, funktioniert Folgendes:
reverse() {
tac <(echo "$@" | tr ' ' '\n') | tr '\n' ' '
}
list="a bb ccc"
for i in `reverse $list`; do
echo "$i"
done
> ccc
> bb
> a
tac
es ein Teil von GNU Coreutils ist. Ihre Lösung ist aber auch eine gute.
tac
. Obwohl von der Anzahl der tac
-losen Antworten hier würde ich vermuten, dass OSX möglicherweise nicht tac hat. Verwenden Sie in diesem Fall eine Variante der @ arp-Lösung - es ist ohnehin einfacher zu verstehen.
find /var/logs/ -name 'foo*.log' -print0 | tail -r | xargs -0 bar
Sollte so funktionieren, wie Sie möchten (dies wurde unter Mac OS X getestet und ich habe eine Einschränkung unten ...).
Auf der Manpage finden Sie:
-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).
Grundsätzlich finden Sie die Dateien, die Ihrem String + glob entsprechen, und schließen jedes mit einem NUL-Zeichen ab. Wenn Ihre Dateinamen Zeilenumbrüche oder andere seltsame Zeichen enthalten, sollte find dies gut handhaben.
tail -r
nimmt die Standardeingabe durch das Rohr und kehrt es (beachten Sie, dass tail -r
Drucke alle auf der Standardausgabe des Eingangs, und nicht nur die letzten 10 Zeilen, die die Standard - Voreinstellung ist.man tail
für weitere Informationen).
Das leiten wir dann weiter an 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).
Hier erwartet xargs Argumente, die durch das NUL-Zeichen getrennt sind, das Sie übergeben find
und mit dem Sie umgekehrt habentail
.
Meine Einschränkung: Ich habe gelesen, dass tail
das mit nullterminierten Strings nicht gut funktioniert . Dies hat unter Mac OS X gut funktioniert, aber ich kann nicht garantieren, dass dies bei allen * nixen der Fall ist. Vorsichtig auftreten.
Ich sollte auch erwähnen, dass GNU Parallel oft als xargs
Alternative verwendet wird. Sie können das auch überprüfen.
Ich kann etwas vermissen, also sollten sich andere melden.
tail -r
... mache ich etwas falsch?
tac
als Alternative erwähnt, also würde ich es stattdessen versuchen
tail -r
ist OSX-spezifisch und kehrt die durch Zeilenumbrüche getrennte Eingabe und nicht die durch Nullen getrennte Eingabe um. Ihre zweite Lösung funktioniert überhaupt nicht (Sie leiten Eingaben an weiter ls
, was nicht wichtig ist). Es gibt keine einfache Lösung, mit der es zuverlässig funktioniert.
In Ihrem Beispiel durchlaufen Sie mehrere Dateien, aber ich fand diese Frage aufgrund des allgemeineren Titels, der auch das Durchlaufen eines Arrays oder das Umkehren basierend auf einer beliebigen Anzahl von Aufträgen abdecken kann.
So geht's in Zsh:
Wenn Sie die Elemente in einem Array durchlaufen, verwenden Sie diese Syntax ( Quelle ).
for f in ${(Oa)your_array}; do
...
done
O
Kehrt die in der nächsten Markierung angegebene Reihenfolge um. a
ist die normale Array-Reihenfolge.
Wie @Gilles sagte, On
werden Ihre globbed-Dateien in umgekehrter Reihenfolge, zB mit my/file/glob/*(On)
. Das liegt daran, dass die On
Reihenfolge der Namen umgekehrt ist .
Zsh-Sortierflags:
a
Array-ReihenfolgeL
Dateilängel
Anzahl der Linksm
Änderungsdatumn
Name^o
umgekehrte Reihenfolge ( o
ist normale Reihenfolge)O
umgekehrte ReihenfolgeBeispiele finden Sie unter https://github.com/grml/zsh-lovers/blob/master/zsh-lovers.1.txt und http://reasoniamhere.com/2014/01/11/outrageously-useful-tips- to-master-your-z-shell /
Mac OSX unterstützt den tac
Befehl nicht. Die Lösung von @tcdyl funktioniert, wenn Sie einen einzelnen Befehl in a aufrufenfor
Schleife . In allen anderen Fällen ist das Folgende der einfachste Weg, um es zu umgehen.
Dieser Ansatz unterstützt keine Zeilenumbrüche in Ihren Dateinamen. Der Grund dafür ist, dass tail -r
die Eingabe durch Zeilenumbrüche getrennt sortiert wird.
for i in `ls -1 [filename pattern] | tail -r`; do [commands here]; done
Es gibt jedoch eine Möglichkeit, die Zeilenumbruchsbeschränkung zu umgehen. Wenn Sie wissen, dass Ihre Dateinamen kein bestimmtes Zeichen enthalten (sagen Sie '='), können Sie tr
alle Zeilenumbrüche ersetzen, um dieses Zeichen zu werden, und dann die Sortierung durchführen. Das Ergebnis würde folgendermaßen aussehen:
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
Hinweis: Abhängig von Ihrer Version von tr
wird dies möglicherweise nicht '\0'
als Zeichen unterstützt. Dies kann normalerweise umgangen werden, indem das Gebietsschema in C geändert wird (aber ich weiß nicht mehr, wie genau, da es nach dem Reparieren jetzt auf meinem Computer funktioniert). Wenn eine Fehlermeldung angezeigt wird und Sie die Problemumgehung nicht finden können, posten Sie sie bitte als Kommentar, damit ich Sie bei der Problembehandlung unterstützen kann.
sort -r
vor demfor
anpfeifen, oder durchwaschenls -r
.