Comment trouver des fichiers entre deux dates en utilisant «trouver»?

21

J'ai un compte de messagerie qui a transmis 60 Go de courriels, et actuellement j'ai beaucoup de mal à utiliser un client de messagerie pour archiver les courriels de l'année dernière (2011).

Via le terminal, j'essaie d'utiliser find pour localiser les fichiers entre le 2011-01-01 et le 2011-12-31, mais en vain.

Comment trouver des fichiers entre deux dates?

Le cas échéant, l'objectif final sera un lot qui déplacera chaque fichier trouvé, correspondant à l'intervalle de dates, vers un dossier.

Zuul
la source
@EliahKagan À l'époque, si la mémoire est bonne, les noms en double n'étaient pas un problème. Néanmoins, si vous alimentez que vous avez le temps, des informations supplémentaires sur un sujet donné sont toujours appréciées :) En outre, j'ai voté pour votre réponse car elle fournit un aperçu supplémentaire sur ce sujet.
Zuul
@EliahKagan Dans ce cas, je vous encourage à fournir une réponse avec la sécurité intégrée que vous avez mise en évidence :)
Zuul

Réponses:

16

Vous pouvez utiliser ce script:

#!/bin/bash
for i in $(find Your_Mail_Dir/ -newermt "2011-01-01" ! -newermt "2011-12-31"); do
  mv $i /moved_emails_dir/
done
Octávio Filipe Gonçalves
la source
6
La sortie de findne doit pas être traitée dans une forboucle shell comme celle-ci, sauf lorsqu'il est garanti qu'aucun fichier ne contient d'espace vide dans son nom. -exec, -execdirOu -print0 | xargsdoit généralement être utilisé à la place; une autre solution possible, qui est généralement beaucoup moins souhaitable mais qui permet d'utiliser une forboucle, est de définir temporairement IFSun espace afin qu'il ne soit pas reconnu comme séparateur de champ.
Eliah Kagan du
@EliahKagan à quoi ressemblerait alors la commande: Remplacez simplement findpar exec? Pourriez-vous ajouter une réponse qui traite de l'utilisation des espaces .. ?? Très appréciée.
SherylHohman
3
@SherylHohman Non, n'utilisez pas la execcommande. Utilisez une findcommande avec l' -execaction à exécuter mv, ou tout ce que vous devez exécuter, comme décrit dans la réponse que j'ai publiée . Lorsque find... -execexécute votre commande avec les noms de chemin qu'elle a trouvés, elle n'utilise pas de shell, donc les espaces ne déclenchent pas le fractionnement ou la globalisation des mots . (Vous voudrez peut-être poster une nouvelle question sur votre cas spécifique, ou demander exactement ce que vous voulez savoir.)
Eliah Kagan
@EliahKagan Désolé, j'ai mal lu votre message - et c'est de vous ! Vous êtes génial! Votre message est excellent ... et merci d'avoir répondu, même si c'était ma propre erreur de lecture !!
SherylHohman
40

Bash recherche des fichiers entre deux dates:

find . -type f -newermt 2010-10-07 ! -newermt 2014-10-08

Renvoie une liste de fichiers qui ont des horodatages après le 2010-10-07 et avant le 2014-10-08

Bash trouve des fichiers d'il y a 15 minutes jusqu'à maintenant:

find . -type f -mmin -15

Renvoie une liste de fichiers qui ont des horodatages après 15 minutes mais avant maintenant.

Bash recherche des fichiers entre deux horodatages:

find . -type f -newermt "2014-10-08 10:17:00" ! -newermt "2014-10-08 10:53:00"

Renvoie des fichiers avec des horodatages entre 2014-10-08 10:17:00et2014-10-08 10:53:00

Eric Leschinski
la source
10

Déplacer les fichiers et inviter l'utilisateur en cas de noms en double:

Comme le montrent les réponses de Subv3rsion et d' Eric Leschinski , le -newermtprédicat sélectionne les fichiers modifiés plus récemment que la date (et l'heure facultative) spécifiée comme opérande. Pour rechercher des fichiers

  • n'importe où srcdir(c'est- à -dire, y compris ses sous-répertoires, leurs sous-répertoires, etc.)
  • dernière modification en (par exemple) septembre 2014
  • et les déplacer versdestdir

...tu peux courir:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -i {} destdir/ \;

Dans une -execexpression, find passe le nom de fichier trouvé à la place de {}. ;signifie -execque la commande à exécuter et ses arguments ont tous été fournis (dans le cas où des expressions ultérieures sont passées pour rechercher après -execles arguments de ce prédicat particulier - voir ci-dessous pour un exemple de cela). ;doit être échappé car \;il n'est pas interprété spécialement par le shell. (Sans \, ;mettrait fin à la findcommande entière , fonctionnant de la même manière qu'une nouvelle ligne. Même si cette findcommande n'a rien après cette -execexpression, le fait de ne pas passer l' ;argument est toujours une erreur de syntaxe.)

Si vous souhaitez simplement répertorier les fichiers - ce qui est conseillé si vous n'êtes pas sûr de la façon dont les anciens e-mails sont stockés ou quels autres fichiers peuvent être présents - omettez -exectout ce qui se trouve à droite. (Pour les e-mails, souvent des e-mails de dates différentes sont stockés dans le même fichier; pour quelqu'un dans la situation décrite dans la question ici, je recommande d'étudier comment ils sont stockés avant de déplacer des fichiers.) Si vous souhaitez à la fois imprimer leurs noms et déplacer eux, ajoutez -printavant -exec.

mv -i invite chaque fois qu'un fichier est écrasé à destination, comme cela se produirait si:

  • un fichier du même nom existe depuis une sauvegarde précédente, ou
  • un fichier du même nom mais d'un sous-répertoire différent de srcdira déjà été déplacé au cours de la même findopération, ou
  • (le moins probable) un fichier du même nom a été créé quelque part au srcdircours de la même findopération, après que l'original a été déplacé mais assez tôt pour être trouvé une fois findtraversé un sous-répertoire différent.

Autres façons d'invoquer rm:

Vous disposez d'autres options pour gérer les fichiers avec des noms en double.

  • Sans -i(c.-à-d. ), Ne demanderait généralement pas l'approbation, mais le ferait si le fichier de destination était en lecture seule. ( peut même réussir à remplacer un fichier en lecture seule parfois, comme si l'utilisateur qui l'exécute est propriétaire du fichier.)mv {} destdir/mvmv
  • Si vous ne voulez même pas ce degré d'interactivité et que vous souhaitez mvtoujours (tenter de) écraser des fichiers portant le même nom, utilisez mv -f.
  • Si, au contraire, vous souhaitez ignorer les fichiers source alors qu'il existe déjà un fichier de destination du même nom, utilisez mv -n.
  • mvaccepte les indicateurs -bet --backuppour renommer automatiquement les fichiers de même nom qui existent déjà à la destination. Par défaut ~est ajouté pour produire le nom de sauvegarde, et si un fichier avec le nom et un fichier avec le nom de sauvegarde existent déjà à la destination, le fichier de sauvegarde est écrasé. Cette valeur par défaut peut être remplacée par les options passées lors de l'appel mvet par les variables d'environnement. Voir man mvpour plus de détails et l'exemple ci-dessous.

Déplacer les fichiers et créer des sauvegardes en cas de noms en double:

Pour déplacer tous les fichiers, sauvegarder des fichiers avec des noms en double à l'aide d'un ~suffixe et utiliser des suffixes numérotés lorsque des fichiers existent déjà (afin d'éviter d'écraser quoi que ce soit), exécutez:.~n~.~

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv --backup=existing {} destdir/ \;

Si vous avez ignoré des fichiers avec des noms en double et que vous souhaitez savoir lesquels:

Si vous utilisez mv -net souhaitez savoir quels fichiers n'ont pas été déplacés car il y avait un autre fichier du même nom, la meilleure façon est probablement d'exécuter à findnouveau la commande d' origine , sans -execet tout à sa droite. Cela imprimera leurs noms.
Il affichera également les noms de tous les fichiers correspondants créés depuis que vous avez exécuté la find .... -exec ...commande d' origine , mais pour cette application, il n'y en aura généralement aucun puisque vous recherchez des fichiers avec d'anciens temps de modification. Il est possible de donner à un fichier un horodatage de modification plus ancien que son âge réel, avec touchet d'autres mécanismes, mais cela ne semble pas susceptible de se produire dans ce cas à votre insu.

Sachant immédiatement que les fichiers sont ignorés en raison de noms en double:

mv -nne signale pas et ne renvoie aucun code de sortie spécial lorsqu'il s'abstient de déplacer un fichier. Donc, si vous souhaitez être immédiatement informé des fichiers ignorés lors des findexécutions, vous devrez effectuer une étape distincte pour cela. Une façon est:

find srcdir -type f -newermt 2014-08-31 ! -newermt 2014-09-30 -exec mv -n {} destdir/ \; \
    -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \; 

Quelques considérations techniques probablement mineures: cela avertit de manière incorrecte si vousmv ne parvient pas à copier un fichier pour une raison différente de celle qui existe à la destination et quitte le signalement du succès . Cela semble peu probable, mais je ne suis pas certain que ce soit impossible. Il souffre également potentiellement d'une condition de concurrence : il avertirait lorsqu'il n'y a aucune erreur réelle, si un nouveau fichier du même nom était créé au même endroit pendant la très courte période après le déplacement de l'ancien fichier et avant la vérification à voir si elle a été supprimée. (Compte tenu de l'application, je doute que l'un ou l'autre problème se produise réellement.) Il pourrait être réécrit pour vérifier la destination avantdéplacer le fichier plutôt qu'après: alors la condition de concurrence serait liée aux fichiers de destination nouvellement créés au lieu des fichiers source. Et bien que les erreurs et avertissements signalés par findou mv(ou [, bien qu'il ne devrait pas y en avoir) soient écrits sur l'erreur standard , notre ...skipped (exists in...avertissement est écrit sur la sortie standard . Normalement, les deux apparaissent sur votre terminal, mais cela peut être important si vous créez des scripts.

J'ai divisé cette commande sur deux lignes pour une lecture plus facile. Il peut être exécuté de cette façon, ou vous pouvez supprimer le \et la nouvelle ligne (c'est-à-dire le saut de ligne).

Comment fonctionne cette findcommande?

findles prédicats peuvent être des tests (comme -typeet -newermt), utilisés pour leurs valeurs de retour, ou des actions (comme -printet-exec ), qui sont souvent utilisés pour leurs effets secondaires.

Lorsqu'aucun opérateur (comme -apour et , -opour ou ) n'est fourni entre les expressions, -aest implicite. findutilise une évaluation de court-circuit pour et et ou . (c'est-à-dire ) n'est vrai que si les expressions p et q sont toutes les deux vraies, donc q n'a pas besoin d'être évalué si p est faux. Bien que nous n'y pensions souvent pas en ces termes, c'est pourquoi les tests doivent être vrais pour que les actions ou tests ultérieurs soient évalués. Par exemple, supposonsp qp -a qfind se trouve un répertoire. Il est évalué -type fà faux, il peut donc tout ignorer par la suite.

Comme les tests, les actions sont également évaluées comme vraies ou fausses. De cette façon, -execsignale si la commande exécutée a quitté le signalement du succès (vrai) ou de l'échec (faux). Nous avons cette chaîne d' -execexpressions liée à implicite et :

-exec mv -n {} destdir/ \; -exec [ -f {} ] \; -exec printf "\`%s' skipped (exists in \`%s')\\n" {} destdir \;

Cela essaie de déplacer le fichier et, en cas d' mvéchec, s'arrête. Nous ne voulons pas avertir d'un fichier correctement ignoré si un autre problème explique pourquoi il n'a pas été déplacé.

Mais s'il réussit, il exécute alors la [commande . Comme find, [prend en charge son propre type d'expressions passées en arguments. [ -f {} ]vérifie si l'opérande après -f(passé à lui findà la place de {}) existe (et est un fichier normal), et retourne soit vrai / succès soit faux / échec.
(Les états de sortie de nombreuses commandes sont mieux interprétés comme signifiant un succès ou un échec, mais[ l'état existant existe généralement mieux comme vrai ou faux.)

S'il [est retourné faux, le fichier a disparu, il a donc été déplacé, il n'y a donc pas besoin de faire quoi que ce soit. Mais s'il [est retourné faux, le fichier est toujours là. findÉvalue ensuite l' -execexpression suivante , qui imprime le message d'avertissement.

Lectures complémentaires

Eliah Kagan
la source
Quand j'aurai le temps, j'espère ajouter une section sur les considérations de performances et -exec ... +avec mv -t, très bientôt.
Eliah Kagan