Comment déplacer les fichiers en fonction de l'année


14

J'ai besoin de déplacer des fichiers en fonction d'un an. J'ai utilisé la findcommande

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

mais pour que cette commande s'exécute avec succès, je dois connaître l'exact mtimemaintenant 470 n'est qu'une supposition. Signifie que si je peux donner l'année 2012, cela me donne des fichiers uniquement liés à 2012.

J'ai donc besoin de conseils pour

Recherchez les fichiers en fonction de l'année, par exemple 2012 et déplacez-les vers un autre répertoire.

OS release 5.2

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

Est-il judicieux d'utiliser à la -exec ls ... \;place de -exec ... +? Votre trouvaille est-elle trop vieille pour ça? Dans ce cas, ce find ... -print0 | xargs -0 ls...serait beaucoup plus rapide.
Hauke ​​Laging du

Je souhaite que ces questions (et réponses) qui traitent des coreutils précisent régulièrement si nous avons affaire à des utilitaires GNU ou BSD (ou autres).
labyrinthe

Réponses:


37

Vous souhaitez utiliser l' -newermtoption pour find:

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

pour obtenir tous les fichiers avec un temps de modification en 2012.

Si votre recherche ne prend pas en charge, -newermtvous pouvez également effectuer les opérations suivantes pour éviter d'utiliser des calculs de décalage:

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 n'est pas disponible dans la commande Rechercher
OmiPenguin

Cela doit être une ancienne version de la découverte que votre RHEL est livrée avec? Je vais fournir une alternative dans la réponse pour cela
Anthon

Oui celui-ci est 5.2
OmiPenguin

Je suppose que c'est la révision de RHEL, pas de find(j'ai trouvé la version 4.4.2)
Anthon

1
Le commutateur newermt n'apparaissait pas dans find jusqu'à des versions après la v4.3.3, gnu.org/software/findutils/manual/html_mono/find.html .
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 n'a aucun sens.


1
-exec ls -lest plus logique et encore plus lors des tests.
un CVn du

@ MichaelKjörling findpeut imprimer tout ce qui lspeut. OK, à une exception près: échapper / citer des caractères désagréables. Mais en général, la sortie de findpeut être triée directement. Les appels inutiles de ls n'accélèrent pas le tout.
Hauke ​​Laging du

J'utilise très souvent quelque chose d'assez similaire (bien que personnellement je préfère -printou peut - être-ls ) lors des tests. L'avantage d'utiliser -exec ls {}est qu'il exécute déjà quelque chose d'extérieur à trouver . Donc, au moment où vous passez de lsà mv, les changements réels sont minimes.
un CVn du

3

Selon la page de manuel, l'argument de -mtime est le nombre de jours que vous recherchez. Vous pouvez utiliser date +%jpour trouver le nombre de jours depuis le 1er janvier de l'année en cours.


2
Belle façon. Pour être très "nitpicky": -mtime -1: est n'importe quel fichier dans les dernières 24 heures. Pas seulement les fichiers d'hier (ou d'aujourd'hui). Donc, il y aura également un petit "chevauchement": si vous déterminez que cela fait 120 jours depuis 2012, et aujourd'hui il est 15h45 lorsque vous lancez le script, vous finirez par sélectionner des fichiers jusqu'au 31 décembre 15h45 ( et pas les derniers de ce jour) ... Vous pouvez probablement utiliser: nb_day - 1, puis "éliminer" les quelques-uns qui datent de 2013 (ceux-ci pourraient être trouvés par un ls -l | grep -v, MAIS les sorties diffèrent si elles ne datent que d'un jour ... beaucoup de pièges ...)
Olivier Dulac

Vous ne voulez utiliser l' -daystartoption que si vous allez travailler avec -mtime. Sinon, vous aurez des problèmes avec les fichiers au début et à la fin de l'année, quelle que soit la façon dont vous tournez, sauf si vous l'exécutez exactement à minuit. Vous pouvez effectuer le décalage avec plus de précision qu'avec -mminqu'avec -mtimesi vous pouvez facilement trouver le nombre de minutes depuis la nouvelle année. Mais le même problème existe avec cela qu'avec -mtime, juste pour moins de fichiers (ceux d'une minute vers minuit).
Anthon

1
Ouais, en relisant la page de manuel, je vois comment cela se décompose en heures, donc faire un simple find -mtime $("date -+%j")ne donnera probablement pas au PO ce qu'il cherche. Je laisse cela à la postérité, car cela semble être un angle mort possible pour les gens.
Bratchley

2

Vous pouvez essayer d'utiliser une combinaison avec les commandes statet / ou datecomme dans les lignes simples suivantes:

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

Dans les deux cas, l'approche consiste à utiliser la datecommande pour extraire l'année de la dernière heure de modification de chaque fichier, puis à construire un chemin avec cette année. La commande mkdir -pcréera ce chemin s'il n'existe pas déjà. Bien sûr, vous pouvez utiliser d'autres findoptions pour affiner votre recherche.


1

Si vous le faites à partir du répertoire de travail, vous pouvez le faire à la place:

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

Cela simplifie considérablement les choses et ne provoque aucun chevauchement. Mais cela suppose également que ces fichiers ont plus de 6 mois, et cela lsimprimera l'année au lieu de l'heure exacte.

Pour les fichiers de moins de 6 mois, il vous suffira de le remplacer par ceci:

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

ou quelque chose de similaire, selon le mois. Si vous souhaitez créer une liste de mois pour déplacer des fichiers (ou si vous souhaitez créer une liste pour des années), procédez comme suit:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.