Einfach sort -rvor dem foranpfeifen, oder durchwaschen ls -r.
David Schwartz
Antworten:
27
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_arraysOption 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];doeval"f=\${$i}"
bar "$f"
i=$((i-1))done
Sobald Sie Positionsparameter verwenden, sind Ihre Variablen iund nicht mehr erforderlich f. führen Sie einfach ein shift, verwenden Sie es $1für Ihren Anruf barund testen Sie es [ -z $1 ]in Ihrem while.
user1404316
@ user1404316 Dies wäre eine übermäßig komplizierte Methode, um die Elemente in aufsteigender Reihenfolge zu durchlaufen . Auch falsch: Weder sind [ -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.
Gilles 'SO- hör auf böse zu sein'
Die Frage besagt ausdrücklich, dass die Dateinamen in / var / log durchlaufen werden. Daher kann man davon ausgehen, dass keiner der Parameter "*" oder leer ist. Ich stehe jedoch in der umgekehrten Reihenfolge korrigiert da.
user1404316
7
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
Gibt es eine Methode, die mit Zeilenumbrüchen funktioniert? (Ich weiß, es ist selten, aber zumindest um zu lernen, möchte ich wissen, ob es möglich ist, korrekten Code zu schreiben.)
Mehrdad
Kreativ, um den Fluss mit tac umzukehren. Wenn Sie unerwünschte Zeichen wie Zeilenumbrüche entfernen möchten, können Sie die Pipe nach tr -d '\ n' ausführen.
Die am häufigsten gewählte Antwort hat die Variable fin meiner Situation gebrochen . Diese Antwort fungiert jedoch als Ersatz für die normale forLeitung.
Serge Stroobandt
2
Wenn jemand versucht, herauszufinden, wie er über eine durch Leerzeichen getrennte Zeichenfolgenliste iterieren kann, funktioniert Folgendes:
Ich habe kein tac auf meinem System; Ich weiß nicht, ob es robust ist, aber ich habe für x in $ {mylist} verwendet. do revv = "$ {x} $ {revv}"; done
arp
@arp Das ist eine Art Schock, wie taces ein Teil von GNU Coreutils ist. Ihre Lösung ist aber auch eine gute.
ACK_stoverflow
@ACK_stoverflow Es gibt Systeme ohne Linux-Userland-Tools.
Kusalananda
@Kusalananda Wollen Sie damit sagen, dass nur Linux GNU-Coreutils verwendet? LOL. Sogar die Busybox hat 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.
ACK_stoverflow
@ACK_stoverflow Das sage ich ja.
Kusalananda
1
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 -rDrucke 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:
-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).
Hier erwartet xargs Argumente, die durch das NUL-Zeichen getrennt sind, das Sie übergeben findund mit dem Sie umgekehrt habentail .
+1 tolle Antwort. Es scheint aber, dass Ubuntu nicht unterstützt tail -r... mache ich etwas falsch?
Mehrdad
1
Nein, das glaube ich nicht. Ich habe meinen Linux-Rechner nicht in Betrieb, aber eine schnelle Google-Suche nach "Linux Tail Man" zeigt ihn nicht als Option an. Sunaku wird tacals Alternative erwähnt, also würde ich es stattdessen versuchen
tcdyl
Ich habe auch die Antwort bearbeitet, um eine andere Alternative aufzunehmen
tcdyl
whoops Ich habe vergessen zu +1, als ich sagte +1 :( Fertig! Entschuldigung, haha :)
Mehrdad
4
tail -rist 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.
Gilles 'SO - hör auf böse zu sein'
1
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. aist die normale Array-Reihenfolge.
Wie @Gilles sagte, Onwerden Ihre globbed-Dateien in umgekehrter Reihenfolge, zB mit my/file/glob/*(On). Das liegt daran, dass die OnReihenfolge der Namen umgekehrt ist .
Mac OSX unterstützt den tacBefehl 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 -rdie 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 tralle Zeilenumbrüche ersetzen, um dieses Zeichen zu werden, und dann die Sortierung durchführen. Das Ergebnis würde folgendermaßen aussehen:
Hinweis: Abhängig von Ihrer Version von trwird 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
.Antworten:
Fügen Sie in bash oder ksh die Dateinamen in ein Array ein und durchlaufen Sie das Array in umgekehrter Reihenfolge.
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: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.
quelle
i
und nicht mehr erforderlichf
. führen Sie einfach einshift
, verwenden Sie es$1
für Ihren Anrufbar
und testen Sie es[ -z $1 ]
in Ihremwhile
.[ -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":
quelle
f
in meiner Situation gebrochen . Diese Antwort fungiert jedoch als Ersatz für die normalefor
Leitung.Wenn jemand versucht, herauszufinden, wie er über eine durch Leerzeichen getrennte Zeichenfolgenliste iterieren kann, funktioniert Folgendes:
quelle
tac
es ein Teil von GNU Coreutils ist. Ihre Lösung ist aber auch eine gute.tac
. Obwohl von der Anzahl dertac
-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.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:
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.
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
: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.
quelle
tail -r
... mache ich etwas falsch?tac
als Alternative erwähnt, also würde ich es stattdessen versuchentail -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 weiterls
, 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 ).
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 mitmy/file/glob/*(On)
. Das liegt daran, dass dieOn
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 /
quelle
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.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: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.quelle
Eine einfache Möglichkeit ist die Verwendung
ls -r
von @David Schwartzquelle
Versuche dies:
Ich denke, es ist der einfachste Weg.
quelle
for
Schleife in umgekehrter Reihenfolge".