In Bash möchte ich eine Funktion erstellen, die den Dateinamen der neuesten Datei zurückgibt, die einem bestimmten Muster entspricht. Zum Beispiel habe ich ein Verzeichnis von Dateien wie:
Directory/
a1.1_5_1
a1.2_1_4
b2.1_0
b2.2_3_4
b2.3_2_0
Ich möchte die neueste Datei, die mit 'b2' beginnt. Wie mache ich das in Bash? Ich muss das in meinem ~/.bash_profile
Skript haben.
Antworten:
Der
ls
Befehl verfügt über einen Parameter-t
zum Sortieren nach Zeit. Sie können dann die erste (neueste) mit greifenhead -1
.Aber Vorsicht: Warum sollten Sie die Ausgabe von ls nicht analysieren?
Meine persönliche Meinung: Das Parsen
ls
ist nur dann gefährlich, wenn die Dateinamen lustige Zeichen wie Leerzeichen oder Zeilenumbrüche enthalten können. Wenn Sie garantieren können, dass die Dateinamen keine lustigen Zeichen enthalten, ist das Parsenls
ziemlich sicher.Wenn Sie ein Skript entwickeln, das von vielen Menschen auf vielen Systemen in vielen verschiedenen Situationen ausgeführt werden soll, empfehle ich dringend, es nicht zu analysieren
ls
.So geht's "richtig": Wie finde ich die neueste (neueste, früheste, älteste) Datei in einem Verzeichnis?
quelle
ls
,printf "%s\n" b2* | head -1
wird dies für Sie erledigt .b2.10_5_2
tötet diese Lösung.Die Kombination von
find
undls
funktioniert gut fürDie Lösung:
Lassen Sie es uns zusammenfassen:
Mit können
find
wir alle interessanten Dateien wie folgt abgleichen:dann können
-print0
wir mit allen Dateinamen sicherls
wie folgt übergeben:Hier können zusätzliche
find
Suchparameter und Muster hinzugefügt werdenls -t
sortiert Dateien nach Änderungszeit (neueste zuerst) und druckt sie einzeln aus. Sie können-c
nach Erstellungszeit sortieren. Hinweis : Dies wird mit Dateinamen unterbrochen, die Zeilenumbrüche enthalten.Endlich bekommen
head -1
wir die erste Datei in der sortierten Liste.Hinweis:
xargs
Verwenden Sie Systembeschränkungen für die Größe der Argumentliste. Wenn diese Größe überschreitet,xargs
wirdls
mehrmals aufgerufen . Dies wird die Sortierung und wahrscheinlich auch die endgültige Ausgabe unterbrechen. Laufum die Grenzen Ihres Systems zu überprüfen.
Hinweis 2: Verwenden
find . -maxdepth 1 -name "my-pattern" -print0
Sie diese Option, wenn Sie keine Dateien in Unterordnern durchsuchen möchten.Anmerkung 3: Wie von @starfry hervorgehoben, verhindert das
-r
Argument fürxargs
den Aufruf vonls -1 -t
, wenn keine Dateien von der übereinstimmenfind
. Vielen Dank für den Vorschlag.quelle
find . -name "my-pattern" ... -print0
gibt mirfind: paths must precede expression: `...'
...
steht für "mehr Parameter". Lass es einfach weg, wenn du es nicht brauchst.-r
, der xargs-Befehlszeile hinzuzufügen , die xargs anweist, seine Befehlszeile nicht auszuführen, wenn an seiner Standardeingabe nichts empfangen wird.-r
der Antwort hinzu.Dies ist eine mögliche Implementierung der erforderlichen Bash-Funktion:
Es verwendet nur integrierte Bash-Dateien und sollte Dateien verarbeiten, deren Namen Zeilenumbrüche oder andere ungewöhnliche Zeichen enthalten.
quelle
nullglob_shopt=$(shopt -p nullglob)
und später$nullglob
wieder zurücksetzen,nullglob
wie es vorher war.$()
oder Backticks) zu vermeiden, da dies insbesondere unter Cygwin langsam ist, selbst wenn der Befehl nur integrierte Funktionen verwendet. Außerdem kann der Subshell-Kontext, in dem die Befehle ausgeführt werden, manchmal dazu führen, dass sie sich unerwartet verhalten. Ich versuche auch zu vermeiden, Befehle in Variablen (wienullglob_shopt
) zu speichern, da sehr schlimme Dinge passieren können, wenn Sie den Wert der Variablen falsch verstehen.cat
!". Auch wenn dies mehr Arbeit erfordert, hat es den Vorteil, Menschen Konzepte zu zeigen. Habe eine +1!Ungewöhnliche Dateinamen (z. B. eine Datei mit dem gültigen
\n
Zeichen können bei dieser Art der Analyse zu Chaos führen. Hier ist eine Möglichkeit, dies in Perl zu tun:Das ist eine Schwartzsche Transformation, die dort verwendet wird.
quelle
Sie können
stat
mit einem Dateikugel und einem Dekorieren-Sortieren-Nichtdekorieren mit der auf der Vorderseite hinzugefügten Dateizeit verwenden:quelle
stat
, wenn ich mich richtig an die Optionen erinnere. Um ähnliche Ausgaben auf anderen Plattformen zu erhalten, können Siestat -c $'%Y\t%n' b2* | sort -rn | head -n1 | cut -f2-
Dunkle magische Funktionsbeschwörung für diejenigen, die die
find ... xargs ... head ...
obige Lösung wünschen , aber in einfach zu verwendender Funktionsform, damit Sie nicht denken müssen:Drucke:
Welches ist:
Der Dateiname mit dem ältesten geänderten Zeitstempel der Datei unter dem angegebenen Verzeichnis, der dem angegebenen Muster entspricht.
quelle
Verwenden Sie den Befehl find.
Angenommen, Sie verwenden Bash 4.2+, verwenden Sie diesen
-printf '%T+ %p\n'
Wert für den Zeitstempel der Datei.Beispiel:
Ein nützlicheres Skript finden Sie im neuesten Suchskript hier: https://github.com/l3x/helpers
quelle
Es gibt einen viel effizienteren Weg, dies zu erreichen. Betrachten Sie den folgenden Befehl:
Dieser Befehl findet die neueste Datei, die vor genau einer Minute mit der Platzhaltersuche auf "b2 *" erstellt wurde. Wenn Sie Dateien aus den letzten zwei Tagen möchten, sollten Sie den folgenden Befehl verwenden:
Das "." repräsentiert das aktuelle Verzeichnis. Hoffe das hilft.
quelle