2010-08-16 9 views
6

Ich bin neu in Shell-Skripting, also brauche ich einige Hilfe brauchen, wie Sie mit diesem Problem umgehen.Holen Sie sich die neueste Datei basierend auf Timestamp

Ich habe ein Verzeichnis, das Dateien im folgenden Format enthält. Die Dateien sind in einem Diretory genannt/incoming/extern/data

AA_20100806.dat 
AA_20100807.dat 
AA_20100808.dat 
AA_20100809.dat 
AA_20100810.dat 
AA_20100811.dat 
AA_20100812.dat 

Wie Sie die Dateinamen der Datei einen Zeitstempel enthalten sehen können. dh [RANGE] _ [JJJJMMTT] .dat

Was ich tun muss, ist herauszufinden, welche dieser Dateien hat das neueste Datum mit dem Zeitstempel auf den Dateinamen nicht der Systemzeitstempel und speichern Sie den Dateinamen in einer Variablen und verschieben Sie es in ein anderes Verzeichnis verschieben und den Rest in ein anderes Verzeichnis verschieben.

+0

Kann [RANGE] eine Kombination aus zwei Zeichen sein? Das macht einen großen Unterschied, wie Sie wahrscheinlich anhand der bereits gegebenen Antworten feststellen werden. –

+0

Ja, sie können anders sein. Und derselbe Ordner enthält auch andere Dateitypen mit Namen, die nicht den oben gezeigten entsprechen. – ziggy

Antwort

17

Für diejenigen, die nur eine Antwort wollen, hier ist es:

ls | sort -n -t _ -k 2 | tail -1 

Hier der Gedanke, der mich hierher geführt hat.

Ich gehe davon aus, dass der [RANGE] Teil alles sein könnte.

Beginnen Sie mit dem, was wir wissen.

  • Arbeitsverzeichnis:/incoming/extern/Daten
  • Format der Dateien: [RANGE] _ [JJJJMMTT] .dat

Wir brauchen die aktuellste [JJJJMMTT] Datei finden in das Verzeichnis, und wir müssen diesen Dateinamen speichern.

Verfügbare Tools (Ich bin die Auflistung nur die entsprechenden Werkzeuge für dieses Problem ... Identifizierung sie wird mit der Praxis einfacher):

Ich denke, wir brauchen nicht sed, da wir mit der gesamten Ausgabe von ls Befehl arbeiten können.Mit ls, awk, sortieren und Heck können wir die richtige Datei wie so (bedenken Sie, dass Sie die Syntax gegen überprüfen, was Ihr Betriebssystem akzeptieren) erhalten:

NEWESTFILE=`ls | awk -F_ '{print $1 $2}' | sort -n -k 2,2 | tail -1` 

Dann ist es nur eine Frage den Unterstrich wieder einzusetzen, was nicht zu schwer sein sollte.

EDIT: Ich hatte ein wenig Zeit, also habe ich den Befehl repariert, zumindest für den Einsatz in Solaris.

Hier ist der gewundene erste Durchlauf (dies setzt voraus, dass ALLE Dateien im Verzeichnis im selben Format sind: [RANGE] _ [yyyymmdd] .dat). Ich wette, es gibt bessere Möglichkeiten, dies zu tun, aber das funktioniert mit meinen eigenen Testdaten (in der Tat fand ich einen besseren Weg, gerade jetzt, siehe unten):

ls | awk -F_ '{print $1 " " $2}' | sort -n -k 2 | tail -1 | sed 's/ /_/' 

... während dieses Schreiben aus Ich entdeckte, dass Sie das einfach tun können:

ls | sort -n -t _ -k 2 | tail -1 

Ich werde es in Teile zerlegen.

ls 

Einfach genug ... ruft die Verzeichnisliste ab, nur Dateinamen. Jetzt kann ich das in den nächsten Befehl pumpen.

awk -F_ '{print $1 " " $2}' 

Dies ist der AWK-Befehl. Sie können eine Eingabezeile verwenden und sie auf eine bestimmte Weise ändern. Hier sage ich nur, dass awk die Eingabe unterbrechen sollte, wo immer ein Unterstrich (_) ist. Ich mache das mit der Option -F. Das gibt mir zwei Hälften jedes Dateinamens. Ich sage dann awk, um die erste Hälfte ($ 1) auszugeben, gefolgt von einem Leerzeichen ("") , gefolgt von der zweiten Hälfte ($ 2). Beachten Sie, dass der Raum der Teil war, der von meinem ursprünglichen Vorschlag fehlte. Dies ist auch nicht notwendig, da Sie im folgenden Sortierbefehl ein Trennzeichen angeben können.

Jetzt wird der Ausgang in jeder Zeile in [RANGE] [JJJJMMTT] .dat aufgeteilt. Jetzt können wir das sortieren:

sort -n -k 2 

Dies nimmt die Eingabe und sortiert es basierend auf dem 2. Feld. Der Befehl sort verwendet standardmäßig Leerzeichen als Trennzeichen. Beim Schreiben dieses Updates habe ich die Dokumentation für sort gefunden, mit der Sie das Trennzeichen angeben können, sodass AWK und SED nicht erforderlich sind. Nehmen Sie die LS und führen Sie sie durch die folgende Sortierung:

Dies erreicht das gleiche Ergebnis. Jetzt wollen Sie nur die letzte Datei, so:

tail -1 

Wenn Sie awk verwendet, um die Datei zu trennen (die nur zusätzliche Komplexität hinzufügt, so tun es nicht sheepish), können Sie den Raum ersetzen ein Unterstrich wieder mit sed:

sed 's/ /_/' 

Einige gute Infos hier, aber ich bin sicher, dass die meisten Leute gehen lesen bis auf den Boden nicht so.

+0

Ich habe das versucht, aber es hat nicht funktioniert. Können Sie erklären, was genau es macht? danke – ziggy

+0

Nun, ich habe nach dem Test aktualisiert. Ich musste etwas in meinem awk-Befehl beheben und entdeckte dann, wie es wirklich nicht gebraucht wurde. Lösung ist an der Spitze, Erklärung ist lang und nicht notwendig, aber ich habe es genossen, es zu schreiben. –

+0

Funktioniert für mich. Bitte, hab mein Baby. –

2

Versuchen:

$ ls -lr 

Hoffe, es hilft.

+0

Hallo, Würde es nicht sortieren mit dem System Zeitstempel für die Datei? Ich war an dem Zeitstempel über den tatsächlichen Dateinamen interessiert. Danke – ziggy

+0

Nein, sortiert die Dateien nach Name nach Ihrem Gebietsschema. Wenn Sie nach dem Systemzeitstempel sortieren möchten, benötigen Sie das Flag "-t". – igor

1

Verwendung:

ls -r -1 AA_*.dat | head -n 1 

(vorausgesetzt, es gibt keine anderen Dateien passende AA_*.dat)

3

sollte diese Arbeit: sind Leerzeichen im Dateinamen

newest=$(ls | sort -t _ -k 2,2 | tail -n 1) 
others=($(ls | sort -t _ -k 2,2 | head -n -1)) 

mv "$newest" newdir 
mv "${others[@]}" otherdir 

Es wird, wenn es nicht funktioniert, obwohl Sie die IFS Variable ändern könnte, beeinflussen.

+0

Hallo, wofür sind die runden Klammern? – ziggy

+0

@ziggy: Meinst du das äußere Set in der zweiten Zeile? Sie erstellen ein Array, das in der letzten Zeile verwendet wird. –

+0

Hallo Dennis, Ich bezog sich sowohl auf die inneren und äußeren runden Klammern. Ich habe versucht, das oben genannte auszuführen, aber die Klammern verursachen Syntaxfehler. Ich benutze die Bourne Shell. Sind diese Korn-Shell-spezifischen Konstrukte? – ziggy

1

Aufgrund der Namenskonvention der Dateien entspricht die alphabetische Reihenfolge der Datumsreihenfolge. Ich bin mir ziemlich sicher, dass in Bash '*' alphabetisch erweitert wird (aber keine Beweise in der Handbuchseite finden), ls sicherlich, so dass die Datei mit dem neuesten Datum, wäre die letzte alphabetisch.

daher in bash

mv $(ls | tail -1) first-directory 
mv * second-directory 

sollte es tun.

Wenn Sie spezifischere über die Auswahl der Datei sein, ersetzen Sie dann * mit etwas anderem - zum Beispiel AA_*.dat

+0

Dies funktioniert auch, aber ich versuche zu vermeiden, mich auf das System verlassen, um die Sortierung für mich (d. H. Über die ls cmd). Danke – ziggy

+0

Warum willst du dich nicht auf 'ls' verlassen - was meinst du mit 'system'? – Beano

1

zu Meiner Lösung zu anderen ähnlich ist, aber ein wenig einfacher.

ls -tr | tail -1 

Was tatsächlich tut, ist auf ls zu verlassen, um die Ausgabe zu sortieren, dann Schwanz verwendet die letzten aufgelistete Dateinamen zu erhalten.

Diese Lösung funktioniert nicht, wenn der von Ihnen benötigte Dateiname einen führenden Punkt (z. B. .profile) enthält.

Diese Lösung funktioniert, wenn der Dateiname ein Leerzeichen enthält.

Verwandte Themen