Comment lister les fichiers qui ont été modifiés dans un certain laps de temps?

38

Comment répertorier de manière récursive tous les fichiers modifiés entre le 22.12.2011 et le 24.12.2011?

serrer
la source
6
Si vous voulez dire «dernier changement», vous avez une chance de trouver une solution. Si un fichier a été modifié le 26.12.2011, vous ne pouvez pas dire s'il a également été modifié pendant votre plage donnée. (Sauf si vous avez un système de fichiers très exotique.)
William Pursell

Réponses:

25

En règle générale, lorsque vous recherchez des fichiers dans un répertoire et ses sous-répertoires de manière récursive, utilisez find.

Le moyen le plus simple de spécifier une plage de dates findconsiste à créer des fichiers aux limites de la plage et à utiliser le -newerprédicat.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop
Gilles, arrête de faire le mal
la source
pourquoi nier la sortie de la première -newerest nécessaire ici?
Alexander Cska
@AlexanderCska Le premier -newern'est pas nié, le second l'est. "Rechercher des fichiers plus récents que startmais pas plus récents que stop".
Gilles 'SO- arrête d'être méchant'
Ok la négation fonctionne sur la commande après. Que se passerait-il si aucune négation n'était présente?
Alexander Cska
@AlexanderCska Ensuite vous obtiendrez les fichiers qui sont plus récents que les deux startet stop.
Gilles, arrête de faire le mal
35

En utilisant la solution de Gilles et après avoir lu l' homme à trouver (1) , j'ai trouvé une solution plus simple. La meilleure option est le -newerXY. Les drapeaux m et t peuvent être utilisés.

m   The modification time of the file reference
t   reference is interpreted directly as a time

Donc la solution est

find . -type f -newermt 20111222 \! -newermt 20111225

La limite inférieure en inclusif et la limite supérieure sont exclusives, alors j’y ai ajouté 1 jour! Et c'est récursif. Cela fonctionne bien sur find v4.5.9.

Vrai
la source
Truc cool, merci! Cela m'a aidé à trouver un fichier récent contenant un mot clé donné dans un répertoire contenant des milliers de fichiers: find -newermt 20150212 \! -newermt 20150213 | xargs grep 'keyword' -m 50 -l( -m 50= recherche dans les 50 premières lignes).
Rob W
@RobW: En fait , vous pouvez épargner le tuyau et xargs en utilisant -exec ... +dans find(1), comme: find -newermt 20150212 \! -newermt 20150213 -exec grep keyword -m 50 -l {} +. Cela fait la même chose, mais moins cher.
TrueY
Je devais joindre les timestamps entre guillemets (je suis sur Ubuntu Xenial avec find 4.7.0-git).
IsaacS
13

Outre les réponses déjà données, notez que vous pouvez directement spécifier vos dates:

find -type f -newermt "2011-12-22" \! -newermt "2011-12-24"

ou

find -type f -newermt "2011-12-22 00:00:00" \! -newermt "2011-12-24 13:23:00"

si vous souhaitez également spécifier l'heure.

étudiant
la source
6

En supposant que vous n’ayez pas besoin de précision aux secondes, cela devrait fonctionner.

find . -type f -mmin -$(((`date +%s`-`date -d 20111222 +"%s"`)/60)) \! -mmin +$(((`date +%s`-`date -d 20111224 +"%s"`)/60))

EDIT: Changé cminpour mminaprès @ commentaire de Eelvex. EDIT: '\!' manquant

onur güngör
la source
hm ne semble pas fonctionner. êtes-vous sûr qu'il parcourt les sous-répertoires de manière récursive?
clamper le
Oui, ça marche sur moi. Avez-vous vraiment des fichiers modifiés dans cette plage de temps? Essayez-le avec différentes plages de temps.
onur güngör
6
-cminest "changement d'état", -mminest "changement de données". Vous voulez probablement-mmin
Eelvex
3

findpeut prendre une date / heure au format ISO. Ainsi, pour un serveur au format UTC, par exemple, vous pouvez spécifier un décalage d’un nombre d’heures peu importe où vous vous trouvez. Cela évite également d’ajouter un jour puisque vous comparez aussi le temps:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800
Alex Young
la source
0

Veuillez noter que la question marquée comme étant en double et, par conséquent, empêchée d'y répondre directement, est la raison pour laquelle je poste ici. Cette réponse sert à répondre à la question "Nécessité de déplacer des fichiers vers un dossier différent en fonction de la date de création [dupliquer]"

Les réponses sont raisonnables mais il y avait quelques limitations avec une commande purement trouver. J'ai écrit ce script shell pour parcourir un répertoire contenant autant de fichiers que le système de fichiers bâillonnait sur les métadonnées en essayant d'exécuter un ls. De plus, certains systèmes * nix verront une erreur de nombre d'arguments trop importante avec ls.

La commande find est très puissante et j'ai commencé avec les méthodes répertoriées, mais j'avais des années de données dans ce répertoire et je devais passer tous les fichiers à plusieurs reprises. Cela produit beaucoup de données inutiles sur chaque fichier. J'ai essayé de faire un écran par an et d'exécuter plusieurs recherches, mais cela a entraîné beaucoup d'erreurs dans chaque recherche et des fichiers disparaissaient lorsque l'une des recherches le déplaçait.

Mon script shell déplace un fichier dans le répertoire de destination, avec une année à 4 chiffres et un mois à 2 chiffres. Il peut facilement être étendu à un jour à 2 chiffres en décommentant quelques lignes et en commentant leurs homologues. Je crois que c’est plus efficace parce que c’est-à-dire qu’il fallait effectuer les déplacements en un seul passage, de sorte que plusieurs commandes de recherche et passages sur le répertoire sont inutiles.

#!/bin/bash
#We want to exit if there is no argument submitted
if [ -z "$1" ]
then
  echo no input file
  exit
fi

#destDir should be set to where ever you want the files to go
destDir="/home/user/destination"

#Get the month and year of modification time
#--format %y returns the modification date in the format:
# 2016-04-26 12:40:48.000000000 -0400
#We then take the first column, split by a white space with awk
date=`stat "$1" --format %y | awk '{ print $1 }'`

#This sets the year variable to the first column split on a - with awk
year=`echo $date | awk -F\- '{print $1 }'`
#This sets the month variable to the second column split on a - with awk
month=`echo $date | awk -F\- '{print $2 }'`
#This sets the day variable to the third column split on a - with awk
#This is commented out because I didn't want to add day to mine
#day=`echo $date | awk -F\- '{print $3 }'`

#Here we check if the destination directory with year and month exist
#If not then we want to create it with -p so the parent is created if
# it doesn't already exist
if [ ! -d $destDir/$year/$month ]
then
  mkdir -p $destDir/$year/$month || exit
fi

#This is the same as above but utilizes the day subdirectory
#Uncommented this out and comment out the similar code above
#if [ ! -d $destDir/$year/$month/$day ]
#then
#  mkdir -p $destDir/$year/$month$day || exit
#fi

#Echoing out what we're doing
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
echo Moving $1 to $destDir/$year/$month
#echo Moving $1 to $destDir/$year/$month/$day

#Move the file to the newly created directory
#The uncommented is for just year/month and the commented line includes day
#Comment the first and uncomment the second if you need day
mv "$1" $destDir/$year/$month
#mv "$1" $destDir/$year/$month/$day

Une fois enregistré et rendu exécutable, vous pouvez appeler ce script avec find comme suit.

find /path/to/directory -type f -exec /home/username/move_files.sh {} \;

Vous n'avez pas besoin de vous inquiéter de la définition de l'option newermt pour find car tout ce que find fournit est une seule exécution par fichier trouvé et le script prend toutes les décisions.

Gardez à l'esprit que si vous ne sélectionnez pas -type f, les répertoires seront déplacés, ce qui causera probablement des problèmes. Vous pouvez également utiliser -type d si vous souhaitez déplacer uniquement des répertoires. Ne pas définir le type provoquera presque certainement un comportement indésirable.

Rappelez-vous que ce script a été adapté à mes besoins. Vous voudrez peut-être simplement utiliser ma construction comme source d'inspiration pour un script mieux adapté à vos besoins. Merci!

Considérations: L’efficacité de la commande peut être grandement améliorée en permettant à un nombre illimité d’arguments de passer à travers le script. C'est en fait relativement facile si vous passez sur la variable $ @. En étendant les fonctionnalités, nous pourrions utiliser la fonction -exec + de find ou tirer parti de xargs, par exemple. Je peux rapidement mettre en œuvre cela et améliorer ma propre réponse, mais c'est un début.

Comme il s’agissait d’une session de script unique, de nombreuses améliorations peuvent probablement être apportées. Bonne chance!

Vex Mage
la source