Fichier batch pour supprimer les fichiers de plus de N jours


678

Je cherche un moyen de supprimer tous les fichiers de plus de 7 jours dans un fichier batch. J'ai cherché sur le Web et j'ai trouvé des exemples avec des centaines de lignes de code et d'autres qui nécessitaient l'installation d'utilitaires de ligne de commande supplémentaires pour accomplir la tâche.

Des choses similaires peuvent être faites dans BASH en seulement quelques lignes de code. Il semble que quelque chose d'au moins à distance pourrait être fait pour les fichiers batch dans Windows. Je recherche une solution qui fonctionne dans une invite de commande Windows standard, sans aucun utilitaire supplémentaire. Veuillez pas non plus PowerShell ou Cygwin.


8
Jeff Atwood a répondu à ceci sur Serverfault qui devrait être documenté ici, je pense. serverfault.com/questions/49614/delete-files-older-than-x-days
Dusty

Une nouvelle méthode basée sur un fichier .BAT qui utilise uniquement les commandes internes CMD.EXE a été publiée ici: stackoverflow.com/questions/9746778/…
Aacini

1
gehrcke.de/timegaps a été conçu à cet effet. Il permet même un schéma de suppression plus sophistiqué: en plus de conserver les fichiers des 7 derniers jours, il permet par exemple également de conserver un fichier pour chacune des 8 dernières semaines, 12, mois, 2 ans.
Dr Jan-Philip Gehrcke

Réponses:


1071

Prendre plaisir:

forfiles -p "C:\what\ever" -s -m *.* -d <number of days> -c "cmd /c del @path"

Voir la forfilesdocumentation pour plus de détails.

Pour plus d'informations, reportez-vous à un index AZ de la ligne de commande Windows XP .

Si vous ne l'avez pas forfilesinstallé sur votre ordinateur, copiez-le depuis n'importe quel Windows Server 2003 vers votre ordinateur Windows XP à l'adresse %WinDir%\system32\. Cela est possible car l'EXE est entièrement compatible entre Windows Server 2003 et Windows XP.

Les versions ultérieures de Windows et Windows Server l'ont installé par défaut.

Pour Windows 7 et plus récent (y compris Windows 10):

La syntaxe a un peu changé. Par conséquent, la commande mise à jour est:

forfiles /p "C:\what\ever" /s /m *.* /D -<number of days> /C "cmd /c del @path"

12
Devrait être del @FILE, le cas est important Je suggère également d'utiliser / c echo @FILE pour les tests
Russell Steen

40
@Russell: @PATH est le chemin complet, y compris le nom. @FILE n'est que le nom, donc si vous avez affaire à des sous-dossiers, cela ne fonctionnera pas.
gregmac

86
Notez que si vous souhaitez des fichiers PLUS anciens que 10 jours, vous devez spécifier -d "-10". -ve signifie "plus ancien que", + ve signifie "plus récent que". Vous pouvez également spécifier le format DDMMYY ou -DDMMYY comme paramètre à -d.
gregmac

42
J'ai utilisé cette syntaxe sur Win Server 2008: forfiles / P "C: \ Mysql_backup" / S / M * .sql / D -30 / C "cmd / c del @PATH"
jman

9
Cette réponse fonctionne lorsque "plus de 7 jours" est défini comme "modifié il y a plus de 7 jours" plutôt que "créé il y a plus de 7 jours". Comment réaliser ce dernier?
TimS

76

Exécutez les commandes suivantes :

ROBOCOPY C:\source C:\destination /mov /minage:7
del C:\destination /q

Déplacez tous les fichiers (en utilisant / mov, qui déplace les fichiers puis les supprime par opposition à / move qui déplace des arborescences entières qui sont ensuite supprimées) via robocopy vers un autre emplacement, puis exécutez une commande de suppression sur ce chemin et vous êtes tous bien.

De plus, si vous avez un répertoire contenant beaucoup de données, vous pouvez utiliser le /mircommutateur


5
Pour la plupart, c'est une réponse assez peu pratique. Si j'ai un répertoire contenant beaucoup de données, il ne fonctionnera pas bien. J'irais avec l'une des réponses qui le fait "en place"
adamb0mb

5
@ adamb0mb ce n'est pas du tout impossible - si "destination" est sur le même système de fichiers que "source" , l'opération de déplacement est assez légère. Comme robocopy est vraiment robuste, il fonctionnera en fait pour n'importe quelle taille de répertoire, des noms de fichiers obscurs, des longueurs de chemin arbitraires et inclura des répertoires si vous en avez besoin - quelque chose qui ne peut sûrement pas être dit à propos de nombreux autres utilitaires Windows. J'utiliserais à la rd /s /q c:\destinationplace de la delcommande ou utiliserais même une autre robocopy /mir c:\emptydir c:\destinationcourse pour vider le répertoire si vous vous attendez à des problèmes avec les noms de fichiers.
syneticon-dj

12
De plus, robocopy prend en charge les chemins UNC - ce qui, à forfilespartir de la réponse acceptée, ne le fera pas.
syneticon-dj

3
Mes pensées étaient plus dans le sens: "Mes fichiers sont déjà là où je les veux. Je ne veux pas avoir à les déplacer." "La suppression de fichiers est logiquement ce que vous faites, alors faites-le. Ne surchargez pas Robocopy pour le faire"
adamb0mb

3
Je recommande ce one-liner pour afficher tous les fichiers de C:\testplus de 7 jours. Pour supprimer les fichiers, changez le echoen del:forfiles /p "C:\test" /m "*.*" /c "cmd /c echo @file" /D -7
PowerUser

25

Ok s'ennuyait un peu et a trouvé cela, qui contient ma version du remplacement de l'époque Linux d'un pauvre limité pour un usage quotidien (pas de rétention de temps):

7daysclean.cmd

@echo off
setlocal ENABLEDELAYEDEXPANSION
set day=86400
set /a year=day*365
set /a strip=day*7
set dSource=C:\temp

call :epoch %date%
set /a slice=epoch-strip

for /f "delims=" %%f in ('dir /a-d-h-s /b /s %dSource%') do (
    call :epoch %%~tf
    if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)
)
exit /b 0

rem Args[1]: Year-Month-Day
:epoch
    setlocal ENABLEDELAYEDEXPANSION
    for /f "tokens=1,2,3 delims=-" %%d in ('echo %1') do set Years=%%d& set Months=%%e& set Days=%%f
    if "!Months:~0,1!"=="0" set Months=!Months:~1,1!
    if "!Days:~0,1!"=="0" set Days=!Days:~1,1!
    set /a Days=Days*day
    set /a _months=0
    set i=1&& for %%m in (31 28 31 30 31 30 31 31 30 31 30 31) do if !i! LSS !Months! (set /a _months=!_months! + %%m*day&& set /a i+=1)
    set /a Months=!_months!
    set /a Years=(Years-1970)*year
    set /a Epoch=Years+Months+Days
    endlocal& set Epoch=%Epoch%
    exit /b 0

USAGE

set /a strip=day*7: Modifiez 7 pour le nombre de jours à conserver.

set dSource=C:\temp : Il s'agit du répertoire de départ pour rechercher les fichiers.

REMARQUES

Il s'agit d'un code non destructif, il affichera ce qui se serait passé.

Changement :

if !epoch! LEQ %slice% (echo DELETE %%f ^(%%~tf^)) ELSE echo keep %%f ^(%%~tf^)

à quelque chose comme:

if !epoch! LEQ %slice% del /f %%f

donc les fichiers sont supprimés

Février : codé en dur à 28 jours. Les années bissextiles sont vraiment un enfer à ajouter. si quelqu'un a une idée qui n'ajouterait pas 10 lignes de code, allez-y et postez-le donc je l'ajoute à mon code.

époque : je n'ai pas pris en compte le temps, car la nécessité est de supprimer des fichiers antérieurs à une certaine date, prendre des heures / minutes aurait supprimé des fichiers d'une journée qui devait être conservée.

LIMITATION

epoch tient pour acquis que votre format de date courte est AAAA-MM-JJ. Il faudrait l'adapter à d'autres paramètres ou à une évaluation au moment de l'exécution (lire sShortTime, configuration liée à l'utilisateur, configurer l'ordre des champs approprié dans un filtre et utiliser le filtre pour extraire les données correctes de l'argument).

Ai-je mentionné que je déteste le formatage automatique de cet éditeur? il supprime les lignes vides et le copier-coller est un enfer.

J'espère que ça aide.


4
+1 pour le code non destructif, je vais essayer de garder cela à l'esprit lorsque je fournirai moi-même des exemples de code.
Haugholt

5
Bien en retard et totalement indépendant, mais 7daysclean.cmdsonne comme un nom génial pour un groupe Synth-Punk.
Flonk

21
forfiles /p "v:" /s /m *.* /d -3 /c "cmd /c del @path"

Vous devriez faire /d -3(3 jours plus tôt) Cela fonctionne très bien pour moi. Ainsi, tous les lots compliqués pourraient être dans la poubelle. Aussi forfilesne prennent pas en charge les chemins UNC, afin d' établir une connexion réseau à un lecteur spécifique.


3
Même erreur que dans les autres réponses (y compris celle acceptée). D'où vient cette étrange habitude de spécifier *.*? Le caractère générique *.*ne correspond pas à tous les fichiers de Windows. Il ne fait correspondre les fichiers avec que .dans leurs noms. L'OP n'a jamais dit quoi exiger .dans le nom du fichier. Le paramètre approprié est /M *, mais c'est de toute façon la valeur par défaut. Il n'y en a pas du tout besoin /M.
2015

@AnT: Êtes-vous sûr? Je pense que *.*se comporte exactement comme *sous Windows. En fait, je viens de l'essayer sur mon ordinateur et, en fait, j'ai dir *.*répertorié test fileun fichier sans extension.
Andreas Rejbrand

1
@Andreas Rejbrand: Je trouve cela surprenant également, mais le traitement de *.*n'est pas cohérent entre, disons, diret l' -moption de forfiles. Le -m *.*masque ignorera en effet les noms de fichiers sans extension, comme je l'ai indiqué dans mon commentaire ci-dessus (essayez-le vous-même). La partie amusante ici est que la documentation MS indique explicitement que -m *.*c'est la valeur par défaut. Cependant, si vous l'essayez dans la vraie vie, vous verrez que la valeur par défaut est en fait -m *- tous les fichiers sont itérés.
2018 à

1
Cette page de documentation MS - technet.microsoft.com/en-us/library/cc753551(v=ws.11).aspx - contient un grand nombre d'erreurs (par exemple dans les exemples) parce que l'auteur du document pensait à tort que le *.*masque appliqué à tous les fichiers. Ma question rethorique sur "cette étrange habitude" était en effet inutile, car le traitement *.*et *comme équivalent est une convention Windows de longue date. Cependant, l' /moption en forfilesarrive à violer cette convention pour une raison quelconque.
AnT

1
Contexte des 5 caractères génériques dans Windows: blogs.msdn.microsoft.com/jeremykuhne/2017/06/04/…
MSalters

18

Jetez un œil à ma réponse à une question similaire :

REM del_old.bat
REM usage: del_old MM-DD-YYY
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do if exist %%~nxa echo %%~nxa >> FILES_TO_KEEP.TXT
for /f "tokens=*" %%a IN ('xcopy *.* /L /I /EXCLUDE:FILES_TO_KEEP.TXT null') do if exist "%%~nxa" del "%%~nxa"

Cela supprime les fichiers antérieurs à une date donnée. Je suis sûr qu'il peut être modifié pour revenir en arrière de sept jours à compter de la date actuelle.

mise à jour: je remarque que HerbCSO a amélioré le script ci-dessus. Je recommande plutôt d' utiliser sa version .


12

Ma commande est

forfiles -p "d:\logs" -s -m*.log -d-15 -c"cmd /c del @PATH\@FILE" 

@PATH - est juste un chemin dans mon cas, j'ai donc dû utiliser @PATH\@FILE

forfiles /?ne fonctionne pas aussi pour moi aussi, maisforfiles (sans "?") a bien fonctionné.

Et la seule question que j'ai: comment ajouter plusieurs masques (par exemple " .log | .bak")?

Tout cela concernant forfiles.exe que j'ai téléchargé ici (sur win XP)

Mais si vous utilisez le serveur Windows, forfiles.exe devrait déjà être là et il diffère de la version ftp. C'est pourquoi je devrais modifier la commande.

Pour Windows Server 2003, j'utilise cette commande:

forfiles -p "d:\Backup" -s -m *.log -d -15 -c "cmd /c del @PATH"

9

Il y a très souvent des questions relatives à la date / heure relative à résoudre avec le fichier batch. Mais l'interpréteur de ligne de commande cmd.exe n'a aucune fonction pour les calculs de date / heure. De nombreuses bonnes solutions de travail utilisant des applications ou des scripts de console supplémentaires ont déjà été publiées ici, sur d'autres pages de Stack Overflow et sur d'autres sites Web.

Pour les opérations basées sur la date / l'heure, il est courant de convertir une chaîne de date / heure en secondes depuis un jour déterminé. Très courant est 1970-01-01 00:00:00 UTC. Mais tout jour ultérieur pourrait également être utilisé en fonction de la plage de dates requise pour prendre en charge une tâche spécifique.

Jay a publié 7daysclean.cmd contenant une solution rapide de "date en secondes" pour l'interpréteur de ligne de commande cmd.exe . Mais il ne prend pas en compte correctement les années bissextiles. JR a publié un module complémentaire pour prendre en compte le jour bissextile de l'année en cours, mais en ignorant les autres années bissextiles depuis l'année de base, c'est-à-dire depuis 1970.

J'utilise depuis 20 ans des tables statiques (tableaux) créées une fois avec une petite fonction C pour obtenir rapidement le nombre de jours y compris les jours intercalaires du 01/01/1970 dans les fonctions de conversion date / heure dans mes applications écrites en C / C ++.

Cette méthode de table très rapide peut également être utilisée dans le code batch à l'aide de la commande FOR . J'ai donc décidé de coder le sous-programme batch GetSecondsqui calcule le nombre de secondes depuis 1970-01-01 00:00:00 UTC pour une chaîne de date / heure passée à cette routine.

Remarque: les secondes intercalaires ne sont pas prises en compte car les systèmes de fichiers Windows ne prennent pas non plus en charge les secondes intercalaires.

Tout d'abord, les tableaux:

  1. Jours depuis 1970-01-01 00:00:00 UTC pour chaque année, y compris les jours bissextiles.

    1970 - 1979:     0   365   730  1096  1461  1826  2191  2557  2922  3287
    1980 - 1989:  3652  4018  4383  4748  5113  5479  5844  6209  6574  6940
    1990 - 1999:  7305  7670  8035  8401  8766  9131  9496  9862 10227 10592
    2000 - 2009: 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245
    2010 - 2019: 14610 14975 15340 15706 16071 16436 16801 17167 17532 17897
    2020 - 2029: 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550
    2030 - 2039: 21915 22280 22645 23011 23376 23741 24106 24472 24837 25202
    2040 - 2049: 25567 25933 26298 26663 27028 27394 27759 28124 28489 28855
    2050 - 2059: 29220 29585 29950 30316 30681 31046 31411 31777 32142 32507
    2060 - 2069: 32872 33238 33603 33968 34333 34699 35064 35429 35794 36160
    2070 - 2079: 36525 36890 37255 37621 37986 38351 38716 39082 39447 39812
    2080 - 2089: 40177 40543 40908 41273 41638 42004 42369 42734 43099 43465
    2090 - 2099: 43830 44195 44560 44926 45291 45656 46021 46387 46752 47117
    2100 - 2106: 47482 47847 48212 48577 48942 49308 49673
    

    Le calcul des secondes pour les années 2039 à 2106 avec une époque commençant le 01/01/1970 n'est possible qu'en utilisant une variable 32 bits non signée, c'est-à-dire non signée longue (ou non signée int) en C / C ++.

    Mais cmd.exe utilise pour les expressions mathématiques une variable 32 bits signée. Par conséquent, la valeur maximale est 2147483647 (0x7FFFFFFF) qui est 2038-01-19 03:14:07.

  2. Information sur l'année bissextile (Non / Oui) pour les années 1970 à 2106.

    1970 - 1989: N N Y N N N Y N N N Y N N N Y N N N Y N
    1990 - 2009: N N Y N N N Y N N N Y N N N Y N N N Y N
    2010 - 2029: N N Y N N N Y N N N Y N N N Y N N N Y N
    2030 - 2049: N N Y N N N Y N N N Y N N N Y N N N Y N
    2050 - 2069: N N Y N N N Y N N N Y N N N Y N N N Y N
    2070 - 2089: N N Y N N N Y N N N Y N N N Y N N N Y N
    2090 - 2106: N N Y N N N Y N N N N N N N Y N N
                                     ^ year 2100
    
  3. Nombre de jours jusqu'au premier jour de chaque mois de l'année en cours.

                       Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
    Year with 365 days:  0  31  59  90 120 151 181 212 243 273 304 334
    Year with 366 days:  0  31  60  91 121 152 182 213 244 274 305 335
    

La conversion d'une date en nombre de secondes depuis le 01/01/1970 est assez simple en utilisant ces tableaux.

Attention, s'il vous plaît!

Le format des chaînes de date et d'heure dépend des paramètres de région et de langue de Windows. Les délimiteurs et l'ordre des jetons affectés aux variables d'environnement Day, Monthet Yeardans la première boucle FOR de GetSecondsdoivent être adaptés au format date / heure local si nécessaire.

Il est nécessaire d'adapter la chaîne de date de la variable d'environnement si le format de date dans la variable d'environnement DATE est différent du format de date utilisé par la commande FOR on %%~tF.

Par exemple, quand se %DATE%développe en Sun 02/08/2015tandis que se %%~tFdéveloppe en 02/08/2015 07:38 PMle code ci-dessous peut être utilisé avec la modification de la ligne 4 à:

call :GetSeconds "%DATE:~4% %TIME%"

Cela se traduit par le passage au sous-programme uniquement 02/08/2015- la chaîne de date sans les 3 lettres de l'abréviation du jour de la semaine et le caractère espace de séparation.

Vous pouvez également utiliser ce qui suit pour passer la date actuelle au format correct:

call :GetSeconds "%DATE:~-10% %TIME%"

Maintenant, les 10 derniers caractères de la chaîne de date sont passés à la fonction GetSecondset, par conséquent, peu importe si la chaîne de date de la variable d'environnement DATE est avec ou sans jour de la semaine tant que le jour et le mois sont toujours avec 2 chiffres dans l'ordre attendu, c'est-à-dire au format dd/mm/yyyy ou dd.mm.yyyy.

Voici le code batch avec des commentaires explicatifs qui sort juste quel fichier supprimer et quel fichier conserver dans l' C:\Temparborescence des dossiers, voir le code de la première boucle FOR .

@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Get seconds since 1970-01-01 for current date and time.
call :GetSeconds "%DATE% %TIME%"
rem Subtract seconds for 7 days from seconds value.
set /A "LastWeek=Seconds-7*86400"

rem For each file in each subdirectory of C:\Temp get last modification date
rem (without seconds -> append second 0) and determine the number of seconds
rem since 1970-01-01 for this date/time. The file can be deleted if seconds
rem value is lower than the value calculated above.

for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
    call :GetSeconds "%%~tF:0"
    rem if !Seconds! LSS %LastWeek% del /F "%%~fF"
    if !Seconds! LEQ %LastWeek% (
        echo Delete "%%~fF"
    ) else (
        echo Keep   "%%~fF"
    )
)
endlocal
goto :EOF


rem No validation is made for best performance. So make sure that date
rem and hour in string is in a format supported by the code below like
rem MM/DD/YYYY hh:mm:ss or M/D/YYYY h:m:s for English US date/time.

:GetSeconds

rem If there is " AM" or " PM" in time string because of using 12 hour
rem time format, remove those 2 strings and in case of " PM" remember
rem that 12 hours must be added to the hour depending on hour value.

set "DateTime=%~1"
set "Add12Hours=0"
if "%DateTime: AM=%" NEQ "%DateTime%" (
    set "DateTime=%DateTime: AM=%"
) else if "%DateTime: PM=%" NEQ "%DateTime%" (
    set "DateTime=%DateTime: PM=%"
    set "Add12Hours=1"
)

rem Get year, month, day, hour, minute and second from first parameter.

for /F "tokens=1-6 delims=,-./: " %%A in ("%DateTime%") do (
    rem For English US date MM/DD/YYYY or M/D/YYYY
    set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
    rem For German date DD.MM.YYYY or English UK date DD/MM/YYYY
    rem set "Day=%%A" & set "Month=%%B" & set "Year=%%C"
    set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)
rem echo Date/time is: %Year%-%Month%-%Day% %Hour%:%Minute%:%Second%

rem Remove leading zeros from the date/time values or calculation could be wrong.
if "%Month:~0,1%"  EQU "0" ( if "%Month:~1%"  NEQ "" set "Month=%Month:~1%"   )
if "%Day:~0,1%"    EQU "0" ( if "%Day:~1%"    NEQ "" set "Day=%Day:~1%"       )
if "%Hour:~0,1%"   EQU "0" ( if "%Hour:~1%"   NEQ "" set "Hour=%Hour:~1%"     )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )

rem Add 12 hours for time range 01:00:00 PM to 11:59:59 PM,
rem but keep the hour as is for 12:00:00 PM to 12:59:59 PM.
if "%Add12Hours%" == "1" (
    if %Hour% LSS 12 set /A Hour+=12
)
set "DateTime="
set "Add12Hours="

rem Must use 2 arrays as more than 31 tokens are not supported
rem by command line interpreter cmd.exe respectively command FOR.
set /A "Index1=Year-1979"
set /A "Index2=Index1-30"

if %Index1% LEQ 30 (
    rem Get number of days to year for the years 1980 to 2009.
    for /F "tokens=%Index1% delims= " %%Y in ("3652 4018 4383 4748 5113 5479 5844 6209 6574 6940 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245") do set "Days=%%Y"
    for /F "tokens=%Index1% delims= " %%L in ("Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N") do set "LeapYear=%%L"
) else (
    rem Get number of days to year for the years 2010 to 2038.
    for /F "tokens=%Index2% delims= " %%Y in ("14610 14975 15340 15706 16071 16436 16801 17167 17532 17897 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550 21915 22280 22645 23011 23376 23741 24106 24472 24837") do set "Days=%%Y"
    for /F "tokens=%Index2% delims= " %%L in ("N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N") do set "LeapYear=%%L"
)

rem Add the days to month in year.
if "%LeapYear%" == "N" (
    for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
    for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)

rem Add the complete days in month of year.
set /A "Days+=Day-1"

rem Calculate the seconds which is easy now.
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"

rem Exit this subroutine
goto :EOF

Pour des performances optimales, il serait préférable de supprimer tous les commentaires, c'est-à-dire toutes les lignes commençant par rem après 0-4 espaces de tête.

Et les tableaux peuvent également être rendus plus petits, c'est-à-dire en diminuant la plage de temps de 1980-01-01 00:00:00 à 2038-01-19 03:14:07 comme actuellement pris en charge par le code de lot ci-dessus, par exemple jusqu'en 2015-01 -01 au 31/12/2019, comme le code ci-dessous l'utilise, ce qui supprime vraiment les fichiers de plus de 7 jours dans l' C:\Temparborescence des dossiers.

De plus, le code de lot ci-dessous est optimisé pour un format horaire de 24 heures.

@echo off
setlocal EnableDelayedExpansion
call :GetSeconds "%DATE:~-10% %TIME%"
set /A "LastWeek=Seconds-7*86400"

for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
    call :GetSeconds "%%~tF:0"
    if !Seconds! LSS %LastWeek% del /F "%%~fF"
)
endlocal
goto :EOF

:GetSeconds
for /F "tokens=1-6 delims=,-./: " %%A in ("%~1") do (
    set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
    set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)
if "%Month:~0,1%"  EQU "0" ( if "%Month:~1%"  NEQ "" set "Month=%Month:~1%"   )
if "%Day:~0,1%"    EQU "0" ( if "%Day:~1%"    NEQ "" set "Day=%Day:~1%"       )
if "%Hour:~0,1%"   EQU "0" ( if "%Hour:~1%"   NEQ "" set "Hour=%Hour:~1%"     )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
set /A "Index=Year-2014"
for /F "tokens=%Index% delims= " %%Y in ("16436 16801 17167 17532 17897") do set "Days=%%Y"
for /F "tokens=%Index% delims= " %%L in ("N Y N N N") do set "LeapYear=%%L"
if "%LeapYear%" == "N" (
    for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
    for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)
set /A "Days+=Day-1"
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"
goto :EOF

Pour encore plus d'informations sur les formats de date et d'heure et les comparaisons d'heure de fichier sous Windows, consultez ma réponse sur savoir si le fichier a plus de 4 heures dans un fichier de commandes avec de nombreuses informations supplémentaires sur les temps de fichier.


9

Copiez ce code et enregistrez-le sous DelOldFiles.vbs.

UTILISATION EN CMD: cscript //nologo DelOldFiles.vbs 15

15 signifie supprimer des fichiers antérieurs à 15 jours.

  'copy from here
    Function DeleteOlderFiles(whichfolder)
       Dim fso, f, f1, fc, n, ThresholdDate
       Set fso = CreateObject("Scripting.FileSystemObject")
       Set f = fso.GetFolder(whichfolder)
       Set fc = f.Files
       Set objArgs = WScript.Arguments
       n = 0
       If objArgs.Count=0 Then
           howmuchdaysinpast = 0
       Else
           howmuchdaysinpast = -objArgs(0)
       End If
       ThresholdDate = DateAdd("d", howmuchdaysinpast, Date)   
       For Each f1 in fc
     If f1.DateLastModified<ThresholdDate Then
        Wscript.StdOut.WriteLine f1
        f1.Delete
        n = n + 1    
     End If
       Next
       Wscript.StdOut.WriteLine "Deleted " & n & " file(s)."
    End Function

    If Not WScript.FullName = WScript.Path & "\cscript.exe" Then
      WScript.Echo "USAGE ONLY IN COMMAND PROMPT: cscript DelOldFiles.vbs 15" & vbCrLf & "15 means to delete files older than 15 days in past."
      WScript.Quit 0   
    End If

    DeleteOlderFiles(".")
 'to here

8

Pour Windows Server 2008 R2:

forfiles /P c:\sql_backups\ /S /M *.sql /D -90 /C "cmd /c del @PATH"

Cela supprimera tous les fichiers .sql datant de plus de 90 jours.


7

Utilisez des forfiles.

Il existe différentes versions. Les premiers utilisent des paramètres de style Unix.

Ma version (pour le serveur 2000 - notez pas d'espace après les commutateurs) -

forfiles -p"C:\what\ever" -s -m*.* -d<number of days> -c"cmd /c del @path"

Pour ajouter des forfiles à XP, obtenez l'exe à partir de ftp://ftp.microsoft.com/ResKit/y2kfix/x86/

et ajoutez-le à C: \ WINDOWS \ system32


11
@Kibbee ce n'est pas la même réponse, la syntaxe est différente. C'était une tentative géniale d'aider. Connaissant très peu la ligne de commande de Windows, j'ai passé des heures de frustration à le faire fonctionner. Les informations clés pour moi étaient le fait qu'il existe différentes versions (avec une syntaxe différente) et que j'avais besoin de supprimer les espaces. Aucune de ces choses n'a été incluse dans la réponse originale. (J'aurais commenté la réponse mais je n'ai pas les privilèges
Aidan Ewen

Même erreur que dans les autres réponses (y compris celle acceptée). Le caractère générique *.*dans forfilesne correspond pas à tous les fichiers. Il ne correspond qu'aux fichiers avec .dans leur nom (c'est-à-dire les fichiers avec des extensions). L'OP n'a jamais dit quoi exiger .dans le nom du fichier. Le paramètre approprié est /M *, mais c'est de toute façon la valeur par défaut. Il n'y en a pas du tout besoin /M.
AnT

7

Pour Windows 2012 R2, les éléments suivants fonctionneraient:

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c del @path"

pour voir les fichiers qui seront supprimés, utilisez ce

    forfiles /p "c:\FOLDERpath" /d -30 /c "cmd /c echo @path @fdate"

Cela fonctionne même dans Windows Server 2008 et supérieur et Windows 7.
kwrl

6

IMO, JavaScript devient progressivement un standard de script universel: il est probablement disponible dans plus de produits que tout autre langage de script (sous Windows, il est disponible à l'aide de l'hôte de script Windows). Je dois nettoyer les anciens fichiers dans de nombreux dossiers, voici donc une fonction JavaScript pour le faire:

// run from an administrator command prompt (or from task scheduler with full rights):  wscript jscript.js
// debug with:   wscript /d /x jscript.js

var fs = WScript.CreateObject("Scripting.FileSystemObject");

clearFolder('C:\\temp\\cleanup');

function clearFolder(folderPath)
{
    // calculate date 3 days ago
    var dateNow = new Date();
    var dateTest = new Date();
    dateTest.setDate(dateNow.getDate() - 3);

    var folder = fs.GetFolder(folderPath);
    var files = folder.Files;

    for( var it = new Enumerator(files); !it.atEnd(); it.moveNext() )
    {
        var file = it.item();

        if( file.DateLastModified < dateTest)
        {
            var filename = file.name;
            var ext = filename.split('.').pop().toLowerCase();

            if (ext != 'exe' && ext != 'dll')
            {
                file.Delete(true);
            }
        }
    }

    var subfolders = new Enumerator(folder.SubFolders);
    for (; !subfolders.atEnd(); subfolders.moveNext())
    {
        clearFolder(subfolders.item().Path);
    }
}

Pour chaque dossier à effacer, ajoutez simplement un autre appel à la fonction clearFolder (). Ce code particulier préserve également les fichiers exe et dll et nettoie également les sous-dossiers.


6

Que diriez-vous de cette modification sur 7daysclean.cmd pour prendre en compte une année bissextile?

Cela peut se faire en moins de 10 lignes de codage!

set /a Leap=0
if (Month GEQ 2 and ((Years%4 EQL 0 and Years%100 NEQ 0) or Years%400 EQL 0)) set /a Leap=day
set /a Months=!_months!+Leap

Édité par Mofi:

La condition mentionnée ci-dessus par JR est toujours fausse raison d'une syntaxe non valide.

Et Month GEQ 2c'est également faux parce que l'ajout de 86400 secondes pour un jour de plus doit être fait au cours d'une année bissextile uniquement pour les mois de mars à décembre, mais pas pour février.

Un code de travail pour prendre en compte le jour bissextile - pour l'année en cours uniquement - dans le fichier de commandes 7daysclean.cmd publié par Jay serait:

set "LeapDaySecs=0"
if %Month% LEQ 2 goto CalcMonths
set /a "LeapRule=Years%%4"
if %LeapRule% NEQ 0 goto CalcMonths
rem The other 2 rules can be ignored up to year 2100.
set /A "LeapDaySecs=day"
:CalcMonths
set /a Months=!_months!+LeapDaySecs

5

Puis-je ajouter une humble contribution à ce fil déjà précieux. Je trouve que d'autres solutions pourraient se débarrasser du texte d'erreur réel mais ignorent le% ERRORLEVEL% qui signale un échec dans mon application. ET je veux légitimement% ERRORLEVEL% aussi longtemps que ce n'est pas l'erreur "Aucun fichier trouvé".

Quelques exemples:

Débogage et élimination de l'erreur en particulier:

forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&ECHO found error||echo found success

Utilisation d'un oneliner pour renvoyer le succès ou l'échec de ERRORLEVEL:

forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&EXIT /B 1||EXIT /B 0

Utiliser un oneliner pour garder le ERRORLEVEL à zéro pour réussir dans le contexte d'un fichier batch au milieu d'un autre code (ver> nul réinitialise le ERRORLEVEL):

forfiles /p "[file path...]\IDOC_ARCHIVE" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&ECHO found error||ver > nul

Pour une étape de travail CmdExec de l'Agent SQL Server, j'ai atterri sur ce qui suit. Je ne sais pas si c'est un bogue, mais le CmdExec de l'étape ne reconnaît que la première ligne de code:

cmd /e:on /c "forfiles /p "C:\SQLADMIN\MAINTREPORTS\SQL2" /s /m *.txt /d -1 /c "cmd /c del @path" 2>&1 |  findstr /V /O /C:"ERROR: No files found with the specified search criteria."2>&1 | findstr ERROR&&EXIT 1||EXIT 0"&exit %errorlevel%

5

Mon Dieu, déjà beaucoup de réponses. Un itinéraire simple et pratique que j'ai trouvé consistait à exécuter ROBOCOPY.EXE deux fois dans un ordre séquentiel à partir d'une seule instruction de ligne de commande Windows à l'aide du paramètre & .

ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 & ROBOCOPY.EXE SOURCE-DIR TARGET-DIR *.* /MOV /MINAGE:30 /PURGE

Dans cet exemple, cela fonctionne en sélectionnant tous les fichiers ( . ) Qui ont plus de 30 jours et en les déplaçant vers le dossier cible. La deuxième commande fait de même avec l'ajout de la commande PURGE, ce qui signifie supprimer les fichiers du dossier cible qui n'existent pas dans le dossier source. Donc, essentiellement, la première commande MOVES et le second DELETES car ils n'existent plus dans le dossier source lorsque la deuxième commande est invoquée.

Consultez la documentation de ROBOCOPY et utilisez le commutateur / L lors des tests.


4

Si vous disposez du kit de ressources XP, vous pouvez utiliser robocopy pour déplacer tous les anciens répertoires dans un seul répertoire, puis utiliser rmdir pour supprimer uniquement celui-ci:

mkdir c:\temp\OldDirectoriesGoHere
robocopy c:\logs\SoManyDirectoriesToDelete\ c:\temp\OldDirectoriesGoHere\ /move /minage:7
rmdir /s /q c:\temp\OldDirectoriesGoHere

4

Je pense que la réponse d'e.James est bonne car elle fonctionne avec des versions non modifiées de Windows dès Windows 2000 SP4 (et peut-être plus tôt), mais cela nécessitait d'écrire dans un fichier externe. Voici une version modifiée qui ne crée pas de fichier texte externe tout en conservant la compatibilité:

REM del_old.cmd
REM usage: del_old MM-DD-YYYY
setlocal enabledelayedexpansion
for /f "tokens=*" %%a IN ('xcopy *.* /d:%1 /L /I null') do @if exist "%%~nxa" set "excludefiles=!excludefiles!;;%%~nxa;;"
for /f "tokens=*" %%a IN ('dir /b') do @(@echo "%excludefiles%"|FINDSTR /C:";;%%a;;">nul || if exist "%%~nxa" DEL /F /Q "%%a">nul 2>&1)

Pour être fidèle à la question d'origine, la voici dans un script qui fait TOUT le calcul pour vous si vous l'appelez avec le nombre de jours comme paramètre:

REM del_old_compute.cmd
REM usage: del_old_compute N
setlocal enabledelayedexpansion
set /a days=%1&set cur_y=%DATE:~10,4%&set cur_m=%DATE:~4,2%&set cur_d=%DATE:~7,2%
for /f "tokens=1 delims==" %%a in ('set cur_') do if "!%%a:~0,1!"=="0" set /a %%a=!%%a:~1,1!+0
set mo_2=28&set /a leapyear=cur_y*10/4
if %leapyear:~-1% equ 0 set mo_2=29
set mo_1=31&set mo_3=31&set mo_4=30&set mo_5=31
set mo_6=30&set mo_7=31&set mo_8=31&set mo_9=30
set mo_10=31&set mo_11=30&set mo_12=31
set /a past_y=(days/365)
set /a monthdays=days-((past_y*365)+((past_y/4)*1))&&set /a past_y=cur_y-past_y&set months=0
:setmonth
set /a minusmonth=(cur_m-1)-months
if %minusmonth% leq 0 set /a minusmonth+=12
set /a checkdays=(mo_%minusmonth%)
if %monthdays% geq %checkdays% set /a months+=1&set /a monthdays-=checkdays&goto :setmonth
set /a past_m=cur_m-months
set /a lastmonth=cur_m-1
if %lastmonth% leq 0 set /a lastmonth+=12
set /a lastmonth=mo_%lastmonth%
set /a past_d=cur_d-monthdays&set adddays=::
if %past_d% leq 0 (set /a past_m-=1&set adddays=)
if %past_m% leq 0 (set /a past_m+=12&set /a past_y-=1)
set mo_2=28&set /a leapyear=past_y*10/4
if %leapyear:~-1% equ 0 set mo_2=29
%adddays%set /a past_d+=mo_%past_m%
set d=%past_m%-%past_d%-%past_y%
for /f "tokens=*" %%a IN ('xcopy *.* /d:%d% /L /I null') do @if exist "%%~nxa" set "excludefiles=!excludefiles!;;%%~nxa;;"
for /f "tokens=*" %%a IN ('dir /b') do @(@echo "%excludefiles%"|FINDSTR /C:";;%%a;;">nul || if exist "%%~nxa" DEL /F /Q "%%a">nul 2>&1)

REMARQUE: Le code ci-dessus prend en compte les années bissextiles, ainsi que le nombre exact de jours dans chaque mois. Le seul maximum est le nombre total de jours écoulés depuis 0/0/0 (après quoi il renvoie des années négatives).

REMARQUE: les mathématiques ne vont que dans un sens; il ne peut pas obtenir correctement les dates futures d'une entrée négative (il essaiera, mais dépassera probablement le dernier jour du mois).


3

Vous pourrez peut-être retirer cela. Vous pouvez jeter un oeil à cette question , pour un exemple plus simple. La complexité vient, lorsque vous commencez à comparer les dates. Il peut être facile de dire si la date est supérieure ou non, mais il existe de nombreuses situations à considérer si vous devez réellement obtenir la différence entre deux dates.

En d'autres termes - n'essayez pas d'inventer cela, sauf si vous ne pouvez vraiment pas utiliser les outils tiers.


3

ce n'est rien d'étonnant, mais je devais faire quelque chose comme ça aujourd'hui et l'exécuter comme tâche planifiée, etc.

fichier de commandes, DelFilesOlderThanNDays.bat ci-dessous avec un exemple d'exécution avec des paramètres:

DelFilesOlderThanNDays.bat 7 C: \ dir1 \ dir2 \ dir3 \ logs * .log

echo off
cls
Echo(
SET keepDD=%1
SET logPath=%2 :: example C:\dir1\dir2\dir3\logs
SET logFileExt=%3
SET check=0
IF [%3] EQU [] SET logFileExt=*.log & echo: file extention not specified (default set to "*.log")
IF [%2] EQU [] echo: file directory no specified (a required parameter), exiting! & EXIT /B 
IF [%1] EQU [] echo: number of days not specified? :)
echo(
echo: in path [ %logPath% ]
echo: finding all files like [ %logFileExt% ]
echo: older than [ %keepDD% ] days
echo(
::
::
:: LOG
echo:  >> c:\trimLogFiles\logBat\log.txt
echo: executed on %DATE% %TIME% >> c:\trimLogFiles\logBat\log.txt
echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
echo: in path [ %logPath% ] >> c:\trimLogFiles\logBat\log.txt
echo: finding all files like [ %logFileExt% ] >> c:\trimLogFiles\logBat\log.txt
echo: older than [ %keepDD% ] days >> c:\trimLogFiles\logBat\log.txt
echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt
::
FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c echo @path" >> c:\trimLogFiles\logBat\log.txt 2<&1
IF %ERRORLEVEL% EQU 0 (
 FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c echo @path"
)
::
::
:: LOG
IF %ERRORLEVEL% EQU 0 (
 echo:  >> c:\trimLogFiles\logBat\log.txt
 echo: deleting files ... >> c:\trimLogFiles\logBat\log.txt
 echo:  >> c:\trimLogFiles\logBat\log.txt
 SET check=1
)
::
::
IF %check% EQU 1 (
 FORFILES /p %logPath% /s /m %logFileExt% /d -%keepDD% /c "cmd /c del @path"
)
::
:: RETURN & LOG
::
IF %ERRORLEVEL% EQU 0 echo: deletion successfull! & echo: deletion successfull! >> c:\trimLogFiles\logBat\log.txt
echo: ---------------------------------------------------------- >> c:\trimLogFiles\logBat\log.txt

3

S'étendant sur la réponse d'Aku, je vois beaucoup de gens poser des questions sur les chemins UNC. Le simple mappage du chemin unc vers une lettre de lecteur rendra les fichiers heureux. Le mappage et le démappage de lecteurs peuvent être effectués par programme dans un fichier de commandes, par exemple.

net use Z: /delete
net use Z: \\unc\path\to\my\folder
forfiles /p Z: /s /m *.gz /D -7 /C "cmd /c del @path"

Cela supprimera tous les fichiers avec une extension .gz qui sont plus anciens que 7 jours. Si vous voulez vous assurer que Z: n'est mappé à rien d'autre avant de l'utiliser, vous pouvez faire quelque chose de simple comme

net use Z: \\unc\path\to\my\folder
if %errorlevel% equ 0 (
    forfiles /p Z: /s /m *.gz /D -7 /C "cmd /c del @path"
) else (
    echo "Z: is already in use, please use another drive letter!"
)

3

La ROBOCOPIE fonctionne très bien pour moi. A l'origine suggéré mon Iman. Mais au lieu de déplacer les fichiers / dossiers vers un répertoire temporaire puis de supprimer le contenu du dossier temporaire, déplacez les fichiers dans la corbeille !!!

Voici quelques lignes de mon fichier batch de sauvegarde par exemple:

SET FilesToClean1=C:\Users\pauls12\Temp
SET FilesToClean2=C:\Users\pauls12\Desktop\1616 - Champlain\Engineering\CAD\Backups

SET RecycleBin=C:\$Recycle.Bin\S-1-5-21-1480896384-1411656790-2242726676-748474

robocopy "%FilesToClean1%" "%RecycleBin%" /mov /MINLAD:15 /XA:SH /NC /NDL /NJH /NS /NP /NJS
robocopy "%FilesToClean2%" "%RecycleBin%" /mov /MINLAD:30 /XA:SH /NC /NDL /NJH /NS /NP /NJS

Il nettoie tout ce qui a plus de 15 jours de mon dossier «Temp» et 30 jours pour tout ce qui se trouve dans mon dossier de sauvegarde AutoCAD. J'utilise des variables car la ligne peut devenir assez longue et je peux les réutiliser pour d'autres emplacements. Il vous suffit de trouver le chemin d'accès à votre corbeille associé à votre connexion.

C'est sur un ordinateur de travail pour moi et ça marche. Je comprends que certains d'entre vous peuvent avoir des droits plus restrictifs, mais essayez quand même;) Recherchez des explications sur les paramètres ROBOCOPY sur Google.

À votre santé!


1
La deuxième réponse la plus votée existante épouse également RoboCopy. Certes, vous utilisez des options quelque peu différentes, mais elles sont proches de la réponse existante.
Jonathan Leffler

2
Ce message a un nouveau contenu - déplacer des fichiers vers la corbeille. Cela n'a pas encore été proposé avec Robocopy et il répond pleinement au message d'origine à l'aide d'une commande intégrée sur une seule ligne. Fonctionne mieux que de combiner les commandes «DEL» et «RMDIR» car les fichiers peuvent être restaurés à partir de la corbeille. Hé, je suis encore nouveau ici - donnez-moi une pause;)
Shawn Pauliszyn

2

Mon script pour supprimer des fichiers antérieurs à une année spécifique:

@REM _______ GENERATE A CMD TO DELETE FILES OLDER THAN A GIVEN YEAR
@REM _______ (given in _olderthanyear variable)
@REM _______ (you must LOCALIZE the script depending on the dir cmd console output)
@REM _______ (we assume here the following line's format "11/06/2017  15:04            58 389 SpeechToText.zip")

@set _targetdir=c:\temp
@set _olderthanyear=2017

@set _outfile1="%temp%\deleteoldfiles.1.tmp.txt"
@set _outfile2="%temp%\deleteoldfiles.2.tmp.txt"

  @if not exist "%_targetdir%" (call :process_error 1 DIR_NOT_FOUND "%_targetdir%") & (goto :end)

:main
  @dir /a-d-h-s /s /b %_targetdir%\*>%_outfile1%
  @for /F "tokens=*" %%F in ('type %_outfile1%') do @call :process_file_path "%%F" %_outfile2%
  @goto :end

:end
  @rem ___ cleanup and exit
  @if exist %_outfile1% del %_outfile1%
  @if exist %_outfile2% del %_outfile2%
  @goto :eof

:process_file_path %1 %2
  @rem ___ get date info of the %1 file path
  @dir %1 | find "/" | find ":" > %2
  @for /F "tokens=*" %%L in ('type %2') do @call :process_line "%%L" %1
  @goto :eof

:process_line %1 %2
  @rem ___ generate a del command for each file older than %_olderthanyear%
  @set _var=%1
  @rem  LOCALIZE HERE (char-offset,string-length)
  @set _fileyear=%_var:~0,4%
  @set _fileyear=%_var:~7,4%
  @set _filepath=%2
  @if %_fileyear% LSS %_olderthanyear% echo @REM %_fileyear%
  @if %_fileyear% LSS %_olderthanyear% echo @del %_filepath%
  @goto :eof

:process_error %1 %2
  @echo RC=%1 MSG=%2 %3
  @goto :eof

1

Celui-ci l'a fait pour moi. Cela fonctionne avec une date et vous pouvez soustraire le montant souhaité en années pour remonter dans le temps:

@echo off

set m=%date:~-7,2%
set /A m
set dateYear=%date:~-4,4%
set /A dateYear -= 2
set DATE_DIR=%date:~-10,2%.%m%.%dateYear% 

forfiles /p "C:\your\path\here\" /s /m *.* /d -%DATE_DIR% /c "cmd /c del @path /F"

pause

le /Fdans lecmd /c del @path /F forces du fichier spécifique à supprimer dans certains cas , le fichier peut être en lecture seule.

la dateYearest la variable d'année et vous pouvez changer le substract à vos propres besoins

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.