dir
hat zwei reguläre Dateien.
file1
hat abc\n
, file2
hat def\n
. Komprimieren Sie diese beiden Dateien mit gzip, wie unten gezeigt,
#ls
#echo 'abc\n' > file1
#echo 'def\n' > file2
#gzip file1
#gzip file2
#ls
file1.gz file2.gz
Nachdem ich den Inhalt überprüft habe,
#find . -type f -name "*.gz" -exec zgrep -Iq . \{} \; -exec zcat \{} \;
def\n
abc\n
Ich erhalte den Inhalt der Dateien nicht in der Reihenfolge ihrer Erstellungszeit. Die erwartete Ausgabe sollte immer sein abc\ndef\n
.
Interessante Beobachtung: Die tatsächliche Ausgabe ist manchmal def\nabc\n
und manchmalabc\ndef\n
Frage:
Wie findet man Dateien in der Reihenfolge (abnehmend/aufsteigend) des Zeitstempels?
Antwort1
Die Reihenfolge der von gemeldeten Dateien find
ist für den Benutzer undurchsichtig. Es kann die Reihenfolge sein, in der sie im Verzeichnis erscheinen. Einige find
Implementierungen sortieren sie nach Inode-Nummer oder anderen Kriterien neu, um die Leistung zu verbessern. Die einzige Möglichkeit, die Reihenfolge zu ändern, besteht über das -depth
Prädikat, find
das Process/Output anweist, vor dem Zweig zu gehen, auf dem sie sich befinden.
Als Alternative zu können Sie die rekursive Glob-Funktion von find
verwenden :zsh
zgrep whatever ./**/*.gz(D.Om)
Der Om
Glob-Qualifizierer dient zum Sortieren nach der Zeit der letzten Änderung (älteste zuerst). .
gilt nur für reguläre Dateien (entspricht find
's -type f
), D
schließt versteckte (Punkt-)Dateien ein, wie find
es standardmäßig der Fall wäre.
Wenn Sie eineArgumentliste zu langFehler, Sie können Folgendes verwenden zargs
:
autoload -U zargs # best in ~/.zshrc
zargs ./**/*.gz(D.Om) -- zgrep whatever
Mit bash
(oder jeder Shell, die Prozessersetzung im Ksh-Stil unterstützt) und aktuellen GNU-Tools wäre das Äquivalent:
xargs -r0a <(
export LC_ALL=C
find . -type f -name '*.gz' -printf '%T@\t%p\0' |
sort -zn | cut -zf2-) zgrep whatever
Antwort2
Eine Möglichkeit besteht darin, den Zeitstempel der Datei zusammen mit dem Dateipfad auszugeben, danach zu sortieren und ihn dann zu entfernen:
find -type f -name "*.gz" -printf '%C@\t%p\n'|sort -nk1|cut -f2-|xargs zcat
Beachten Sie, dass wenn Ihre Dateinamen möglicherweise unsichere Zeichen (wie Leerzeichen) enthalten können, ersetzen Sie einfach
xargs zcat
mit
xargs -d "\n" zcat
und wenn Sie die Zeilenumbrüche in den Dateinamen berücksichtigen müssen, können Sie zum Beenden von Datensätzen ein Nullbyte verwenden, wie in der Antwort von @stéphane-chazela beschrieben (obwohl dies in der Praxis selten ein Problem darstellt).
Antwort3
Leider funktioniert der Find-Befehl so, dass die Ausgabe nicht unbedingt alphabetisch oder nach Dateialter sortiert ist. Sie könnten etwas wie Folgendes versuchen:
ls -1dtr $(find . -maxdepth 1 -type f -name '*.gz') | xargs gzcat $1