Ruft Dateien mit einem Namen ab, der einen Datumswert enthält, der kleiner oder gleich einem bestimmten Eingabedatum ist

7

Einer meiner Ordner enthält Dateien im folgenden Format:

3_20150412104422154033.txt
3_2015041211022775012.txt
3_20150412160410171639.txt
3_20150412160815638933.txt
3_20150413161046573097.txt
3_20150413161818852312.txt
3_20150413163054600311.txt
3_20150413163514489159.txt
3_2015041321292659391.txt
3_20150414124528747462.txt
3_20150414125110440425.txt
3_20150414134437706174.txt
3_20150415085045179056.txt
3_20150415100637970281.txt
3_20150415101749513872.txt

Ich möchte Dateien abrufen, deren Datumswert kleiner oder gleich meinem eingegebenen Datumswert ist.

Wenn ich beispielsweise "3_20150414" (3_YYYYMMDD) gebe, möchte ich, dass die Ausgabe die Dateinamen sind

3_20150412104422154033.txt
3_2015041211022775012.txt
3_20150412160410171639.txt
3_20150412160815638933.txt
3_20150413161046573097.txt
3_20150413161818852312.txt
3_20150413163054600311.txt
3_20150413163514489159.txt
3_2015041321292659391.txt
3_20150414124528747462.txt
3_20150414125110440425.txt
3_20150414134437706174.txt

Ich kann die Dateien auflisten, indem ich einen Befehl wie diesen gebe:

ls -l | grep '20150413\|20150414' |awk '{print $NF}'

Aber ich kämpfe darum, eine <=Übereinstimmung zu finden .

Vermögen
quelle
1
+1 für die Verwendung des JJJJMMTT-Formats, mit dem Datumszeichenfolgen als Zahlen behandelt (und korrekt verglichen) werden können.
G-Man sagt "Reinstate Monica"

Antworten:

6

Sie können awkund seinen String-Vergleichsoperator verwenden.

ls | awk '$0 < "3_20150415"'

In einer Variablen:

max=3_20150414 export max
ls | LC_ALL=C awk '$0 <= ENVIRON["max"] "z"'

Durch die Verkettung mit "z" wird hier sichergestellt, dass es sich bei dem Vergleich um einen Zeichenfolgenvergleich handelt, und es ist jederzeit an diesem Tag möglich, da im CGebietsschema die Ziffern zuvor sortiert werden z.

Stéphane Chazelas
quelle
2

grephat keinen ≤ Betreiber per se , aber es gibt eine kludgy Art und Weise zu fälschen. Sie möchten alle Daten zwischen dem Jahr 0 (oder dem Jahr 1; je nachdem, welches erste Jahr war) bis 20150414. (Ich gehe davon aus, dass BC-Daten vom Tisch sind.) Teilen Sie diesen Bereich in Unterbereiche auf, die durch reguläre Ausdrücke abgeglichen werden können:

  • Jahr 0 bis 1999 - alle Jahre beginnen mit 0 oder 1, also grep for [01].
    (Es wird davon ausgegangen, dass alle regulären Ausdrücke am Zeilenanfang direkt nach dem „3_“ verankert sind.)
  • Jahr 2000 bis 2009 - Regex 200.
  • Jahr 2010 bis 2014 - Regex 201[0-4].
  • Jahr 2015, Monat 1 bis Monat 3 - 20150[1-3].
  • Jahr 2015, Monat 4, Tag 1 bis 9 - 2014040
  • Jahr 2015, Monat 4, Tag 10 bis 14 - 2014041[0-4]

und dann alle zusammenfügen:

grep -E '3_([01]|200|201[0-4]|20150[1-3]|2015040|2015041[0-4])'

ls -lNatürlich erhalten Sie viele Informationen zu den Dateien (Modus, Besitzer, Mod-Zeit usw.), die Sie nicht benötigen. Sie können awk '{print $NF}'sie also entfernen und nur den Dateinamen belassen. Dies ist ineffizient und fehleranfällig (es bricht ab, wenn ein Dateiname ein Leerzeichen oder eine Registerkarte enthält). Das Parsen der Ausgabe von lsist nie eine gute Idee, aber Sie können es ein wenig sicherer machen, indem Sie es ein wenig einfacher machen: Erhalten Sie einfach nicht die Informationen, die Sie nicht wollen oder brauchen, und dann müssen Sie sie nicht verwerfen .

ls | grep -E '3_([01]|200|201[0-4]|20150[1-3]|2015040|2015041[0-4])'

sollte gut genug sein.

Das Erstellen dieses sechsteiligen regulären Ausdrucks ist jedoch mühsam und fehleranfällig und schwierig (wenn auch nicht unmöglich) zu schreiben. Hier ist ein sauberer Weg:

ls | awk 'substr($1, 3, 8) <= 20150414'

Dies extrahiert die acht Zeichen beginnend mit der 3. Position (dh nach dem „3_“) und vergleicht sie mit 20150414 als zwei achtstellige Zahlen.

G-Man sagt "Reinstate Monica"
quelle
1

Mögliche Lösung anhand Ihres Beispiels:

ls -l | grep '3_2015' | awk -v d='3_20150414' '{ s = substr($NF, 1, 10); if (length(s) == 10 && s <= d) print $NF; }'

Ich habe Ihr Grep-Muster ein wenig geändert und den gesuchten Wert als Argument an das übergeben, awkwo wir nur Zeichenfolgen vergleichen, um die gewünschten Dinge auszugeben.
Es gibt auch viele Artikel, warum Sie nicht analysieren sollten,ls also ändere ich es ein wenig mit find:

find . -type f -name '*3_2015*' -printf "%f\n" | awk -v d='3_20150414' '{ s = substr($NF, 1, 10); if (length(s) == 10 && s <= d) print $NF; }'
Taliezin
quelle