Shell Script - Obtenez tous les fichiers modifiés après <date>

136

Je préfère ne pas faire cela en PHP, donc j'espère qu'une personne décente au script shell pourra vous aider.

J'ai besoin d'un script qui parcourt le répertoire de manière récursive et trouve tous les fichiers dont la dernière date de modification est supérieure à une certaine date. Ensuite, il tarera et compressera le (s) fichier (s) en conservant les informations de chemin.

Jonathan Leffler
la source
14
Bonne décision de ne pas le faire en PHP.
Kredns
1
Vous pouvez utiliser n'importe lequel des langages de script shell décents, par exemple python, ruby, perl sans recourir à php.
garrow
3
@garrow Ce serait en fait assez simple en PHP en utilisant un RecursiveDirctoryIterator encapsulé dans un FilterIterator.
Artefacto

Réponses:

136

aussi simple que:

find . -mtime -1 | xargs tar --no-recursion -czf myfile.tgz

find . -mtime -1sélectionnera tous les fichiers dans le répertoire courant (récursivement) modifié la veille. vous pouvez utiliser des fractions, par exemple:

find . -mtime -1.5 | xargs tar --no-recursion -czf myfile.tgz
skrat
la source
4
Voir la réponse de user104848 ci-dessous pour savoir comment gérer les espaces dans vos noms de fichiers
Brian Henk
8
La conversion d'un horodatage arbitraire en une durée relative fractionnaire ne semble ni correcte ni particulièrement pratique. La solution ci-dessous en utilisant -newermtest beaucoup plus agréable.
Bobby Jack
5
Lorsque vous essayez d'extraire des fichiers avec des modifications dans une structure avec des répertoires, les répertoires eux-mêmes sont marqués comme modifiés, ce qui entraîne l'archivage du dossier entier. Ajouter -type fpour sélectionner uniquement les fichiers. Cela maintient la structure des dossiers, mais ne sauvegarde que les fichiers avec les modifications.
Brent
1
@BrianHenk user104848 changé leur nom, je suis sûr que vous voulez dire cette réponse de (actuellement) Jason Luther bien
icc97
4
La question demande de rechercher des fichiers à une date arbitraire. Cette réponse est de savoir comment trouver des fichiers par un nombre arbitraire de jours dans le passé. Je ne pense pas que cela devrait être la réponse acceptée sans ajouter une étape pour convertir une date en un delta de jour.
Mark
91

Si vous avez GNU find, alors il existe une légion d'options pertinentes. Le seul hic, c'est que l'interface avec eux est moins que stellaire:

  • -mmin n (temps de modification en minutes)
  • -mtime n (temps de modification en jours)
  • -newer file (heure de modification plus récente que l'heure de modification du fichier)
  • -daystart (ajuster l'heure de début de l'heure actuelle au début de la journée)
  • Plus des alternatives pour le temps d'accès et le temps de «changement» ou de «création».

Le plus difficile est de déterminer le nombre de minutes depuis un moment.

Une option à considérer: utiliser touchpour créer un fichier avec l'horodatage de modification requis; puis utilisez findavec -newer.

touch -t 200901031231.43 /tmp/wotsit
find . -newer /tmp/wotsit -print
rm -f /tmp/wotsit

Cela recherche les fichiers plus récents que 2009-01-03T12: 31: 43. Clairement, dans un script, il y /tmp/wotsitaurait un nom avec le PID ou une autre valeur pour le rendre unique; et il y aurait un trappour s'assurer qu'il est supprimé même si l'utilisateur interrompt, et ainsi de suite.

Jonathan Leffler
la source
65
Au lieu de cela, vous pouvez utiliser -newermt '2009-01-03T12:31:43'pour éviter d'avoir à créer un fichier juste pour référence.
Michael Mior
@MichaelMior: Intéressant - le 'find' sur les supports MacOS X 10.7.2 -newermt(documenté sous -newerXYcar il y a plusieurs options; X = m, Y = t dans ce cas). La découverte GNU sur les systèmes Linux (presque archaïques) que j'utilise ne supporte pas les options, c'est donc une arrivée relativement récente. Merci pour l'information.
Jonathan Leffler
Cette option est présente dans GNU find 4.4.2 que j'utilise sur mon système.
Michael Mior
2
Notez également que GNU find prend également en charge les temps relatifs, c'est-à-dire. -newermt '-2 weeks'.
Cybolic
1
-newermt '2009-01-03T12:31:43'semble génial, mais malheureusement, il semble tout interpréter dans le mauvais fuseau horaire: lists.gnu.org/archive/html/bug-findutils/2012-12/msg00009.html
antoine
35

Vous pouvez le faire directement avec tar et encore mieux:

tar -N '2014-02-01 18:00:00' -jcvf archive.tar.bz2 files

Cela demande à tar de compresser les fichiers plus récents que le 1er janvier 2014, 18:00:00.

linux_newbie
la source
9
Huh ... J'utilise Unix depuis 1984 et je ne l'ai jamais su. Toujours quelque chose à apprendre.
John
Les implémentations de tarqui viennent avec OS X et FreeBSD ne prennent en charge --newerque la longue option pour -NGNU tar.
nisetama
C'est génial ... Je n'ai pu le faire fonctionner qu'avec bzip, sans utiliser -xcvf et une extension gz ... mais je ne suis pas un expert.
phil
17

Cela fonctionnera pour un certain nombre de fichiers. Vous voulez inclure "-print0" et "xargs -0" au cas où l'un des chemins contiendrait des espaces. Cet exemple recherche les fichiers modifiés au cours des 7 derniers jours. Pour trouver ceux modifiés avant les 7 derniers jours, utilisez "+7".

find . -mtime -7 -print0 | xargs -0 tar -cjf /foo/archive.tar.bz2

Comme cette page l' avertit, xargs peut provoquer l'exécution de la commande tar plusieurs fois s'il y a beaucoup d'arguments, et l'indicateur "-c" peut causer des problèmes. Dans ce cas, vous voudriez ceci:

find . -mtime -7 -print0 | xargs -0 tar -rf /foo/archive.tar

Vous ne pouvez pas mettre à jour une archive tar compressée avec tar, vous devrez donc bzip2 ou gzip dans un second temps.

Jason Luther
la source
1
En ce qui concerne le deuxième point, vous pouvez utiliser une commande tar compatible gzip, comme l'option -z de Gnu tar, pour mettre également à jour les archives compressées.
Suncat2000
Ou ajoutez l'option 'j' pour utiliser bzip dans les tars GNU récents
hd1
3
Comme je l'ai dit ci-dessus à propos de la réponse de Jonathan, cela récupérera les dossiers qui ont des changements entraînant l'importation de tous leurs fichiers. Ajouter -type fpour sélectionner uniquement les fichiers. Cela maintient la structure des dossiers, mais ne sauvegarde que les fichiers avec des modifications / ajoutées récemment.
Brent
12

Cela devrait afficher tous les fichiers modifiés au cours des 7 derniers jours.

find . -type f -mtime -7 -print

Transformez cela en tar / zip, et vous devriez être bon.

Chris Doggett
la source
4

Je ferais simplement ce qui suit pour sauvegarder tous les nouveaux fichiers d'il y a 7 jours

tar --newer $(date -d'7 days ago' +"%d-%b") -zcf thisweek.tgz .

notez que vous pouvez également remplacer «il y a 7 jours» par tout ce qui correspond à vos besoins

Peut être : date -d'yesterday' +"%d-%b"

Ou même : date -d'first Sunday last month' +"%d-%b"

Michel
la source
3

bien sous Linux, essayez de lire la page de manuel de la commande find

man find

quelque chose comme ça devrait

 find . -type f -mtime -7 -print -exec cat {} \; | tar cf - | gzip -9

et tu l'as

Luixv
la source
3

Vous pouvez obtenir une liste des fichiers modifiés pour la dernière fois il y a x jours avec:

find . -mtime -x

Ensuite, il vous suffit de tarer et de compresser les fichiers dans la liste résultante, par exemple:

tar czvf mytarfile.tgz `find . -mtime -30`

pour tous les fichiers modifiés le mois dernier.

mouviciel
la source
3
"-mtime x" correspond aux fichiers modifiés il y a exactement "x" jours, utilisez "-mtime -x" pour faire correspondre les fichiers modifiés il y a moins de "x" jours.
Lance Richardson
2

Ce script trouvera les fichiers ayant une date de modification de deux minutes avant et après la date donnée (et vous pouvez modifier les valeurs dans les conditions selon vos besoins)

PATH_SRC="/home/celvas/Documents/Imp_Task/"
PATH_DST="/home/celvas/Downloads/zeeshan/"

cd $PATH_SRC
TODAY=$(date  -d "$(date +%F)" +%s)
TODAY_TIME=$(date -d "$(date +%T)" +%s)


for f in `ls`;
do
#       echo "File -> $f"
        MOD_DATE=$(stat -c %y "$f")
        MOD_DATE=${MOD_DATE% *}
#       echo MOD_DATE: $MOD_DATE
        MOD_DATE1=$(date -d "$MOD_DATE" +%s)
#       echo MOD_DATE: $MOD_DATE

DIFF_IN_DATE=$[ $MOD_DATE1 - $TODAY ]
DIFF_IN_DATE1=$[ $MOD_DATE1 - $TODAY_TIME ]
#echo DIFF: $DIFF_IN_DATE
#echo DIFF1: $DIFF_IN_DATE1
if [[ ($DIFF_IN_DATE -ge -120) && ($DIFF_IN_DATE1 -le 120) && (DIFF_IN_DATE1 -ge -120) ]]
then
echo File lies in Next Hour = $f
echo MOD_DATE: $MOD_DATE

#mv $PATH_SRC/$f  $PATH_DST/$f
fi
done

Par exemple , vous voulez que les fichiers ayant la date de modification avant la seule date donnée, vous pouvez changer 120pour 0en $DIFF_IN_DATEparamètre rejeter les conditions de $DIFF_IN_DATE1paramètre.

De même, si vous voulez que les fichiers aient une date de modification 1 heure avant et après la date donnée, remplacez simplement 120par 3600in if CONDITION.

Zeeshan Ali
la source