So wählen Sie die älteste Datei in einem Ordner aus dem Verzeichnis aus

So wählen Sie die älteste Datei in einem Ordner aus dem Verzeichnis aus

In meinem Verzeichnis befinden nsich mehrere Dateien ../in/. Von diesen Dateien möchte ich die älteste Datei verarbeiten und an das ../complete/Verzeichnis senden. Die übrigen Dateien werden an das ../error/Verzeichnis gesendet. Kann jemand helfen?

Antwort1

So kopieren Sie die älteste Datei nach ../complete:

cp -v "$(find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '1s/[0-9,\.]\+ //p')" ../complete

So kopieren Sie alles außer dem ältesten nach ../error:

find ../in -maxdepth 1 -type f -printf '%T@ %p\0' | sort -zn | \
  sed -zn '2,$s/[0-9,\.]\+ //p' | xargs -0 cp -vt ../error

Erläuterung:

  • find
    • -maxdepth 1geht nur eine Ebene nach unten; daher wird das Verzeichnis nicht rekursiv durchsucht.
    • -type fnur Dateien abgleichen.
    • -printf '...'ein benutzerdefiniertes Ausgabeformat. %T@gibt den letzten Änderungszeitpunkt der Datei in einem Zeitstempel an, %pist der Name der Datei. Beachten Sie das \0am Ende. Die Dateien werden durch Nullbytes getrennt gedruckt, nicht durch Zeilenumbrüche, da der Zeilenumbruch wahrscheinlich ein Zeichen im Dateinamen sein könnte, was dann den Befehl unterbrechen würde.
  • sort -znDadurch wird die Ausgabe durch Null-Bytes getrennt () gelesen -zund numerisch sortiert ( -n).
  • sed -znliest die Ausgabe durch Null-Bytes getrennt.
    • 1stimmt nur mit der ersten Zeile überein (erster Befehl) und 2,$mit allen anderen (zweiter Befehl)
    • s/[0-9,\.]\+ //pentfernt den führenden Zeitstempel aus der Ausgabe.
  • Nur ab dem zweiten Befehl: xargs -0 cp -vt ../errorVerarbeitet die Ausgabe durch Null-Bytes getrennt ( -0) und ruft cp -vt ../errorbei allen Eingaben auf, welche die Dateien kopieren.

Beispielausgabe:

$ ls -lt ../in/
total 0
-rw-r--r-- 1 user user 0 Jun 24 08:18 file2
-rw-r--r-- 1 user user 0 Jun 24 08:18 file3
-rw-r--r-- 1 user user 0 Jun 24 08:18 file4
-rw-r--r-- 1 user user 0 Jun 24 08:18 file5
-rw-r--r-- 1 user user 0 Jun 24 08:17 file_oldest
$ cp -v "$(...)" ../complete
'../in/file_oldest' -> '../complete/file_oldest'
$
$ find ... | xargs ... ../error
'../in/file2' -> '../error/file2'
'../in/file3' -> '../error/file3'
'../in/file4' -> '../error/file4'
'../in/file5' -> '../error/file5'

Antwort2

Um die älteste Datei zu finden und sie in das gewünschte Verzeichnis zu verschieben, verwenden Sie:

# cd to ../in/

$ ls -lt | grep -v '^d' | tail -1 | awk '{print $NF}' | xargs -I '{}' mv '{}' ../complete/

Nachdem Ihre älteste Datei nun ausgelagert wurde, können Sie alle Dateien nach../error/

$ mv -- * ../error/

Das --Folgende mvist erforderlich, wenn Ihre Datei-/Verzeichnisnamen mit einem beginnen -.

Antwort3

Aufbauend aufRahuls Antwort:

$ ls -ltr | grep -v '^d' | awk 'NR==2 {print $NF; exit}' | xargs -I '{}' mv -- '{}' ../complete/

Anmerkungen:

  • Sie sagen, Sie möchten etwas mit „der ältesten Datei“ machen. Alle Antworten gehen davon aus, dass Sie „am wenigsten kürzlich geändert“ meinen. Wenn Sie „am wenigsten kürzlich geändert“ meinengeändert, sagen Sie es; die Antworten werden etwas anders sein. Wenn Sie zuletzt meinenerstellt, was Sie wollen, ist unter Unix fast unmöglich.
  • ls -lt(was Rahul verwendet hat) listet das aktuelle Verzeichnis im Langformat in der Reihenfolge nach Änderungsdatum/-zeit auf, wobei das Neueste zuerst und das Älteste zuletzt ist.  ls -ltrist dasRalles davon; die ältesten zuerst und die neuesten zuletzt.
  • Wenn Sie möglicherweise Dateien haben, deren Namen mit einem Punkt beginnen (.), fügen Sie die AOption zu hinzu ls; z. B. ls -ltrA. (Die Reihenfolge der Optionen ist egal; Sie können ls -ltAr, ls -lAtr, oder sogar verwenden ls -ltr -A, wenn Sie möchten.)
  • Ich habe gelogen. Eine lange lsAuflistung eines Verzeichnisses hat immer eine totalZeile am Anfang. In ls -ltrsteht der älteste Eintrag auf derzweiteLinie.
  • grep -v '^d'filtert die Verzeichnisse heraus (sofern vorhanden).
  • awk 'NR==2 { print $NF; exit }' druckt das letzte Feld (den Dateinamen*) aus der zweiten Zeile (der ältesten Datei) und beendet dann das Programm.

    • Dies ist ein Prozess weniger als tail -1 | awk '{print $NF}'.
    • Dies könnte schneller funktionieren, da beim awkBeenden lsmöglicherweise auch beendet wird und Sie so die Generierung der Liste für das gesamte Verzeichnis vermeiden würden.
    • Sie können das Problem beseitigen, grepindem Sie Folgendes tun:

      ls -ltr | awk '! /^d/ { count++ } count==2 { print $NF; exit }'
      

      aber ich würde davon abraten. Zu komplexe Skripte sind schwer zu warten.

  • Das --Danachmv im xargsBefehlist notwendig, wenn Sie Dateinamen haben, die mit einem beginnen-.
  • Sie brauchen das nicht wirklich xargs. Sie können den obigen Befehl vereinfachen zu

    $ mv -- $(ls -ltr | grep -v '^d' | awk 'NR==2 { print $NF; exit }') ../complete/
    

________
* Wie in Rahuls Antwort schlägt dies fehl, wenn der Dateiname Leerzeichen oder Tabulatoren enthält – und noch schlimmer, wenn er Zeilenumbrüche enthält.

Wenn Sie möglicherweise Dateien haben, deren Namen mit einem Punkt beginnen (.), shopt -s dotglobbevor Sie die

$ mv -- * ../error/

verwandte Informationen