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 vers
destdir
...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