web-dev-qa-db-fra.com

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

Comment lister récursivement tous les fichiers qui ont été modifiés entre le 22.12.2011 et le 24.12.2011?

40
clamp

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

La façon la plus simple de spécifier une plage de dates avec find est de créer des fichiers aux limites de la plage et d'utiliser le -newer prédicat.

touch -t 201112220000 start
touch -t 201112240000 stop
find . -newer start \! -newer stop

En utilisant la solution de Gilles et après avoir lu man find (1) , j'ai trouvé une solution plus simple. La meilleure option est -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

La solution est donc

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

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

38
TrueY

En plus des réponses déjà données, notez que vous pouvez spécifier directement 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.

15
student

En supposant que vous n'avez pas besoin de précision sur les 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é cmin en mmin après le commentaire de @ Eelvex. MODIFIER: '\!' manquant

6
onur güngör

find peut prendre une date/heure au format ISO, donc pour un serveur sur UTC par exemple, vous pouvez spécifier un décalage d'un certain nombre d'heures où que vous soyez. Cela évite également d'ajouter un jour car vous comparez également le temps:

find -type f -newermt 20111224T0800 \! -newermt 20111225T0800
3
Alex Young

Veuillez noter que la question marquée en double, et qu'il est donc impossible d'y répondre directement, c'est pourquoi je poste ici. Cette réponse est pour répondre à la question "besoin 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 find. J'ai écrit ce script Shell pour parcourir un répertoire contenant tant de fichiers que le système de fichiers bâillonnait les métadonnées en essayant d'effectuer un ls. De plus, certains systèmes * nix éviteront une erreur d'arguments trop importante avec l'exécution de ls.

La commande find est très puissante et j'ai commencé par les méthodes répertoriées, mais j'avais tellement d'années de données dans ce répertoire que j'ai dû passer tous les fichiers à plusieurs reprises. Cela produit beaucoup d'inutiles passés 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 de chaque découverte et les fichiers disparaissaient lorsque l'une des découvertes la déplaçait.

Mon script Shell déplace un fichier vers le répertoire de destination, avec une année à 4 chiffres et un mois à 2 chiffres. Il peut facilement être étendu à une journée à 2 chiffres en décommentant quelques lignes et en commentant leurs homologues. Je pense qu'il est plus efficace car il a effectué les mouvements en une seule passe de recherche, de sorte que plusieurs commandes de recherche et passes sur le répertoire ne sont pas nécessaires.

#!/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 à vous soucier de définir 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, cela déplacera les répertoires et cela causera probablement des problèmes. Vous pouvez également utiliser -type d si vous cherchez à déplacer uniquement les répertoires. Ne pas définir le type produira presque certainement un comportement indésirable.

N'oubliez pas que ce script a été adapté aux besoins de mes. Vous voudrez peut-être simplement utiliser ma construction comme source d'inspiration pour un script mieux adapté à vos besoins. Je vous remercie!

Considérations: L'efficacité de la commande peut être GRANDEMENT améliorée en permettant à un nombre illimité d'arguments de passer par le script. C'est en fait relativement facile si vous passez sur la variable $ @. L'extension de la fonctionnalité de ceci nous permettrait d'utiliser la fonction -exec + de find ou de tirer parti des 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!

0
Vex Mage