So verschieben Sie die Dateien nach Jahr


14

Ich muss Dateien basierend auf einem Jahr verschieben. Ich habe den findBefehl verwendet

find /media/WD/backup/osool/olddata/ -mtime +470 -exec ls -lrth {} \;|sort -k6

Aber damit dieser Befehl erfolgreich ausgeführt werden kann, muss ich genau wissen, dass es sich bei mtime470 nur um eine Vermutung handelt. Bedeutet, wenn ich das Jahr 2012 angeben kann, werden nur Dateien angezeigt, die sich auf 2012 beziehen.

Also brauche ich Ratschläge, wie es geht

Finden Sie Dateien basierend auf dem Jahr, z. B. 2012, und verschieben Sie sie in ein anderes Verzeichnis.

OS release 5.2

FIND version
GNU find version 4.2.27
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION SELINUX 

Ist es sinnvoll, -exec ls ... \;statt zu verwenden -exec ... +? Ist dein Fund dafür zu alt? In diesem Fall find ... -print0 | xargs -0 ls...wäre viel schneller.
Hauke ​​Laging

Ich wünschte, diese Fragen (und Antworten), die sich mit coreutils befassen, würden routinemäßig angeben, ob es sich um GNU- oder BSD- (oder andere) Utils handelt.
Labyrinth

Antworten:


37

Sie möchten die -newermtOption verwenden für find:

find /media/WD/backup/osool/olddata/ -newermt 20120101 -not -newermt 20130101

alle Dateien mit Änderungszeit im Jahr 2012 zu bekommen.

Wenn Ihre Suche dies nicht unterstützt -newermt, können Sie auch Folgendes tun, um die Verwendung von Offset-Berechnungen zu verhindern:

touch -d 20120101 /var/tmp/2012.ref
touch -d 20130101 /var/tmp/2013.ref
find /media/WD/backup/osool/olddata/ -newer /var/tmp/2012.ref -not -newer /var/tmp/2013.ref

1
-newermt flag ist nicht verfügbar in Befehl Suchen
OmiPenguin

Das muss eine alte Version von find sein, mit der Ihr RHEL geliefert wird? Ich werde in der Antwort darauf eine Alternative
Anthon

Ja, das ist 5.2
OmiPenguin

Ich nehme an, das ist die Revision von RHEL, nicht von find(ich habe Version 4.4.2 gefunden)
Anthon

1
Der Schalter newermt wurde erst in Versionen nach v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html , in find angezeigt .
SLM

5
touch --date=2011-12-31T23:59:59 start
touch --date=2012-12-31T23:59:59 stop
find / -newer start \! -newer stop -printf %Tx" "%p\\n

-exec ls macht keinen Sinn.


1
-exec ls -l macht mehr Sinn und noch mehr beim Testen.
ein CVn

@ MichaelKjörling findkann alles drucken was lskann. OK, mit einer Ausnahme: Entkommen / Zitieren von unangenehmen Zeichen. Im Allgemeinen kann die Ausgabe von findjedoch direkt sortiert werden. Nutzlose Anrufe von ls beschleunigen das Ganze nicht.
Hauke ​​Laging

Ich benutze sehr oft etwas ganz ähnliches (obwohl ich persönlich bevorzuge -printoder möglicherweise -ls ) beim Testen. Der Vorteil von using -exec ls {}ist, dass es bereits etwas externes ausführt, um zu finden . Wenn Sie also von lsauf wechseln , mvsind die tatsächlichen Änderungen minimal.
ein CVn

3

Laut der Manpage ist das Argument für -mtime die Anzahl der Tage, nach denen Sie suchen. Mit können date +%jSie die Anzahl der Tage seit dem 1. Januar des aktuellen Jahres ermitteln.


2
Netter Weg. Sehr "nitpicky" zu sein: -mtime -1: ist eine beliebige Datei in den letzten 24 Stunden. Nicht nur die Dateien von gestern (oder heute). Es wird also auch eine kleine "Überlappung" geben: Wenn Sie feststellen, dass seit 2012 120 Tage vergangen sind und es heute 15:45 Uhr ist, wenn Sie das Skript starten, werden Sie am Ende Dateien bis zum 31. Dezember 15:45 Uhr auswählen ( und nicht die letzten an diesem Tag) ... Sie können wahrscheinlich Folgendes verwenden: nb_day - 1, und dann die wenigen aus dem Jahr 2013 "aussortieren" (diese könnten von einem ls -l | grep -v gefunden werden, ABER Die Ausgabe unterscheiden sich, wenn sie nur 1 Tag alt sind ... viele Gefahren ...)
Olivier Dulac

Sie möchten die -daystartOption verwenden, wenn Sie mit arbeiten möchten -mtime. Andernfalls haben Sie Probleme mit Dateien zu Beginn und am Ende des Jahres, egal wie Sie sich umdrehen, es sei denn, Sie führen dies genau um Mitternacht aus. Sie können den Offset mit genauer machen -mminals mit, -mtimewenn Sie die Anzahl der Minuten seit dem neuen Jahr leicht finden können. Aber es gibt das gleiche Problem wie bei -mtime, nur für weniger Dateien (diese eine Minute gegen Mitternacht Neujahr).
Anthon

1
Ja, ich lese die Manpage noch einmal durch und sehe, wie sie sich in Stunden aufteilt. Wenn man also einfach handelt, find -mtime $("date -+%j")bekommt das OP wahrscheinlich nicht das, was sie wollen. Ich überlasse es jedoch der Nachwelt, da dies ein möglicher blinder Fleck für Menschen ist, in den man hineinfallen kann.
Bratchley

2

Sie können versuchen, eine Kombination mit den Befehlen statund / oder datewie in den folgenden Einzeilern zu verwenden:

BSD / Mac OS X:

find . -type f -print | while read file; do eval `stat -s "$file"`; year=`date -jf "%s" "+%Y" "$st_mtime"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

Linux:

find . -type f -print | while read file; do year=`date -r "$file" "+%Y"`; dest="/path/to/destination/$year; mkdir -p "$dest"; mv "$file" "$dest"; done

In beiden Fällen wird der dateBefehl verwendet, um das Jahr aus dem letzten Änderungszeitpunkt jeder Datei zu extrahieren und anschließend einen Pfad mit diesem Jahr zu erstellen. Der Befehl mkdir -perstellt diesen Pfad, falls er noch nicht vorhanden ist. Natürlich können Sie auch andere findOptionen verwenden, um Ihre Suche zu verfeinern.


1

Wenn Sie dies aus dem Arbeitsverzeichnis heraus tun, können Sie dies stattdessen tun:

ls -l |awk '{ if ($8 == "2013") print $9 }'

Dies vereinfacht die Dinge erheblich und verursacht keine Überlappung. Es wird jedoch auch davon ausgegangen, dass diese Dateien älter als 6 Monate sind und lsdas Jahr anstelle der genauen Uhrzeit gedruckt wird.

Bei Dateien, die älter als 6 Monate sind, müssen Sie sie nur durch folgende ersetzen:

ls -l |awk '{ if ($6 == "May") print $9 }' 

oder etwas ähnliches, je nach Monat. Wenn Sie eine Liste von Monaten erstellen möchten, für die Dateien verschoben werden sollen (oder wenn Sie eine Liste für Jahre erstellen möchten), gehen Sie folgendermaßen vor:

month="May Jun Jul"; 
for i in `echo $month`; 
do 
    for j in `ls -l |awk '{ if ($6 == "'$i'") print $9}'`
    do
        mkdir -p $i
        mv $j $i
    done
done
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.