Wie liste ich Dateien auf, die älter als ein Tag sind und deren Dateiname „2015“ enthält?

11

Ich möchte alle Protokolldateien auflisten, die heute nicht gehören, und nur die Dateien, die 2015in ihren Namen enthalten sind.

Dies sind die Befehle, die ich versucht habe:

find . -name 2015 -mtime +1 -exec  ls -ltrh  {} \;
find . -name *2015* -mtime +1 -exec  ls -ltrh  {} \;

Die Ausgabe von beiden ist nichts, aber dennoch sind Dateien vorhanden. Mit diesen Befehlen stimmt etwas nicht, und ich verstehe nicht, was. Jede Hilfe wäre dankbar.

rɑːdʒɑ
quelle
Das findTeil sieht für mich gut aus, aber ich hatte auch Probleme mit dem -execParameter. Ich konnte das auch nicht zum Laufen bringen. (Ich habe versucht, alle JPG-Dateien von einem Ordner in das übergeordnete Verzeichnis zu verschieben - und habe es dann manuell gemacht ...)
Byte Commander
2
Vielleicht möchten Sie einen Blick darauf werfen, warum find -mtime +1 nur Dateien zurückgibt, die älter als 2 Tage sind.
Steeldriver
@steeldriver Ich denke, das ist wirklich das, was hier falsch läuft, denn wenn es Dateien im aktuellen Verzeichnis mit 2015ihrem Namen gäbe (das andere offensichtliche Manko der Art und Weise, wie der Befehl geschrieben wird), vermute ich, dass es irgendeine Art von Ausgabe geben würde. Vielleicht möchten Sie eine Antwort dazu posten.
Eliah Kagan

Antworten:

18

Der Befehl find . -name '*2015*' -mmin +1440 -lswird wahrscheinlich tun, was Sie wollen. Siehe unten für Details.

Dein erster Befehl hatte -name 2015. Es hat nicht funktioniert, da nur Dateien gefunden werden, deren Namen genau sind 2015 und keine anderen Zeichen enthalten.

Ihr zweiter Befehl ist find . -name *2015* -mtime +1 -exec ls -ltrh {} \;möglicherweise aus mehreren Gründen fehlgeschlagen:

1. Nicht zitierte *Zeichen werden von der Shell erweitert und dann an weitergeleitet find.

Wenn es irgendwelche Dateien direkt im enthaltenen aktuellen Verzeichnis (der du bist in , wenn Sie diesen lief find ...Kommando) , deren Namen 2015(und nicht mit einem Start .), dann die Schale expandiert *2015*in eine Liste dieser Dateinamen, dann übergeben diese Liste als Argumente für find. Dies ist nicht das, was Sie wollen - stattdessen möchten Sie *2015*buchstäblich als Argument übergeben, um zu finden, damit findund nicht die Shell herausfinden kann, welche Dateien damit übereinstimmen.

Um dieses Problem zu beheben, zitieren Sie *2015*. Es gibt drei gängige Methoden:

  • '*2015*'(dh find . -name '*2015*' -mtime +1 -exec ls -ltrh {} \;)
  • "*2015*"(dh find . -name "*2015*" -mtime +1 -exec ls -ltrh {} \;)
  • \*2015\*(dh find . -name \*2015\* -mtime +1 -exec ls -ltrh {} \;)

Ich schlage vor , das Schreiben es mit einfachen Anführungszeichen wie '*2015*', denn:

Aber in diesem Fall spielt es keine Rolle. 'und "beide behandeln *dasselbe und der Ausdruck ist nicht kompliziert genug, um zu \zitieren, um es schwer zu verstehen.

2. -mtime +1Wählt nur Dateien aus, die vor zwei oder mehr Tagen geändert wurden.

Wie man findsagt:

       Numeric arguments can be specified as

       +n     for greater than n,

       -n     for less than n,

       n      for exactly n.
       -mtime n
              File's data was last modified n*24 hours ago.  See the  comments
              for -atime to understand how rounding affects the interpretation
              of file modification times.
       -atime n
              File was last accessed n*24 hours ago.  When  find  figures  out
              how  many  24-hour  periods  ago the file was last accessed, any
              fractional part is ignored, so to match -atime +1, a file has to
              have been accessed at least two days ago.

Angenommen, eine Datei wurde vor 47 Stunden geändert. Um herauszufinden , wie viele 24-Stunden - Perioden , die sind, findRunden nach unten : Es ist ein Zeitraum von 24 Stunden vor. Aber -mtime +1Matches nur Dateien , deren Änderungszeiten sind streng mehr als ein Zeitraum von 24 Stunden vor. Daher stimmen die Dateien von gestern nicht überein.

Siehe Warum gibt find -mtime +1 nur Dateien zurück, die älter als 2 Tage sind? Für weitere Informationen, wie von Steeldriver vorgeschlagen .

Um Dateien zu finden, die zuletzt vor mehr als 24 Stunden geändert wurden , empfehle ich stattdessen, sie als vor 1440 Minuten festzulegen mit -mmin +1440:

find . -name '*2015*' -mmin +1440 -exec ls -ltrh {} \;

Einige Leser fragen sich vielleicht, warum ich nicht zitiert habe {}. Einige Leute zitieren {}, um die Menschen daran zu erinnern, dass es kein Ausdruck für die Erweiterung der Zahnspange ist . Bourne-style Schalen (wie bash ) nicht benötigen {}mit nichts drin zu zitieren. Vielleicht wird es von einer Shell außerhalb des Bourne-Stils besonders behandelt. Das könnte der Grund sein, warum einige Benutzer es zitieren. Es gibt aber auch ein Missverständnis, dass man manchmal zitieren muss {}, -execum Dateinamen mit Leerzeichen korrekt zu behandeln. Die; s falsch: mit {}oder '{}', finderhält die gleichen Argumente, wie die Shell die Anführungszeichen entfernt , bevor er '{}'zufind. Um diesem Missverständnis entgegenzuwirken, zitiere ich nicht {}, aber es ist eine Frage des Stils - wenn Sie lieber {}dokumentieren möchten , wie die Shell nicht behandelt, {und }das ist in Ordnung.

Ich empfehle Ihnen auch, entweder Ihren lsBefehl zu ändern oder (wie von muru vorgeschlagen ) durch die Aktion von find's zu ersetzen -ls. ls -ltrhtut wahrscheinlich nicht das, was Sie beabsichtigen, da es für jede gefundene Datei separat ausgeführt wird und daher die Flags -tund -r, die die Sortierung angeben, irrelevant sind.

Obwohl die Ausgabe etwas anders formatiert wird als mit ls -l, ist die Verwendung -lseinfacher und einfacher.

find . -name '*2015*' -mmin +1440 -ls

Oder wenn Sie entscheiden, dass Sie wirklich nur die Dateinamen (einschließlich ihrer Pfade relativ zu .) auflisten müssen, können Sie einfach keine Aktion angeben, wodurch die Standardaktion -printverwendet wird:

find . -name '*2015*' -mmin +1440
Eliah Kagan
quelle
1
Schöne gründliche Antwort! Zumindest mit GNU find gibt es auch die newerXYSyntax, die Kalenderargumente akzeptiert, zB -newermt 'yesterday'und! -newermt 'yesterday'
steeldriver
Weißt du was ? Sie sind fantastisch. @ Eliah Kagan
rɑːdʒɑ
Danke stell Fahrer, das sind sehr gute Informationen aus dem Link zu wissen. Aber in meinem Fall, da es sich um ein Anwendungsprotokoll aus alten Anwendungsdateien handelt, gab es keine Möglichkeit, Änderungen vorzunehmen.
Nochmals vielen
2

Zitieren Sie den Ausdruck und ich schlage vor, dass Sie auch die Klammern zitieren

find . -name "2015" -mtime +1 -exec  ls -ltrh  '{}' \;

oder

find . -name "*2015*" -mtime +1 -exec  ls -ltrh  '{}' \;

Sie müssen die gefundenen Dateien nicht an ls übergeben

find . -name "*2015*" -mtime +1
Panther
quelle
Vielleicht die Verwendung einschränken -type f? Und wenn lsverwendet werden muss, schlagen Sie vor -ls.
Muru
1
Klar, alle guten Vorschläge. Ich bin nicht sicher, was das OP will, und ich glaube, die Ursache des Problems ist das Fehlen von Anführungszeichen um das Suchmuster "-name".
Panther
2

In zsh können Sie verwenden Glob-Qualifizierer verwenden (dies ist eine einzigartige zsh-Funktion, die in anderen Shells wie bash nicht verfügbar ist).

ls -ltr *2015*(m+1)

Dies listet nur Dateien im aktuellen Verzeichnis auf. zuVerwenden Sie rekursiven Durchlaufen von Verzeichnissen

ls -ltr **/*2015*(m+1)

Mit find, -name 2015findet nur Dateien , deren Namen genau 2015. -name *2015*Funktioniert nur, wenn keine Dateien vorhanden sind, deren Name 2015im aktuellen Verzeichnis enthalten ist, da die Shell das Muster erweitert, *2015*bevor findes aufgerufen wird. Sie müssen das Muster zitieren:

find -name '*2015*' -mtime +1 …

Beachten Sie, dass sowohl find -mtime +1als auch zsh *(m+1)Dateien finden, die mindestens 48 Stunden alt sind , und keine Dateien, die älter als heute sind. Das Pluszeichen bedeutet „streng mehr als“ und die Anzahl der Tage wird abgerundet. Verwenden Sie -mtime +0oder, um Dateien zu finden, die mindestens 24 Stunden alt sind (m+0).

Wenn Sie Dateien zu finden , die zuletzt geändert wurden gestern oder vor , können Sie findmit dem -newermtPrädikat :

find -name '*2015*' ! -newermt 'today 0:00' …

Es gibt keine wirklich bequeme Möglichkeit, diesen Test in zsh durchzuführen.

Gilles 'SO - hör auf böse zu sein'
quelle