web-dev-qa-db-fra.com

Commande par lots date et heure dans le nom du fichier

Je compresse des fichiers à l’aide de WinZip sur la ligne de commande. Comme nous archivons quotidiennement, j'essaie d'ajouter la date et l'heure à ces fichiers afin qu'un nouveau fichier soit généré automatiquement à chaque fois.

J'utilise ce qui suit pour générer un nom de fichier. Copier le coller sur votre ligne de commande et vous devriez voir un nom de fichier avec un composant Date et heure.

echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.Zip

Sortie

Archive_20111011_ 93609.Zip

Cependant, mon problème est AM vs PM. L'horodatage AM me donne l'heure 9 (avec un espace vide au début) par rapport à 10 qui occupe naturellement les deux espaces. 

Je suppose que mon problème s'étendra aux neuf premiers jours, aux neuf premiers mois, etc.

Comment puis-je résoudre ce problème afin que les zéros au début soient inclus au lieu des espaces vides afin d'obtenir Archive_20111011_093609.Zip?

59
Raj More

Une autre solution:

for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I

Cela vous donnera (indépendamment des paramètres régionaux!):

  20130802203023.304000+120
( YYYYMMDDhhmmss.<milliseconds><always 000>+/-<timedifference to UTC>  )

A partir de là, c'est facile:

set datetime=%datetime:~0,8%-%datetime:~8,6%
20130802-203023

Pour que Logan demande le même format de sortie pour la "date-heure modifiée" d'un fichier:

for %%F in (test.txt) do set file=%%~fF
for /f "tokens=2 delims==" %%I in ('wmic datafile where name^="%file:\=\\%" get lastmodified /format:list') do set datetime=%%I
echo %datetime%

C'est un peu plus compliqué, car il ne fonctionne qu'avec des chemins complets, wmic s'attend à ce que les barres obliques inverses soient doublées et le = à échapper (le premier. Le second est protégé par des guillemets).

54
Stephan

Extraire l'heure, chercher un espace de repère, le cas échéant, remplacer par un zéro;

set hr=%time:~0,2%
if "%hr:~0,1%" equ " " set hr=0%hr:~1,1%
echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%hr%%time:~3,2%%time:~6,2%.Zip
54
Alex K.

Vous devriez chercher; vous pouvez simplement remplacer tous les espaces par zéro set hr=%hr: =0% - jeb11 octobre '11 à 14:16

Alors j'ai fait:

set hr=%time:~0,2%
set hr=%hr: =0%

Ensuite, utilisez %hr% dans la chaîne que vous formatez pour obtenir toujours une heure à deux chiffres.

(Le commentaire de Jeb sous la réponse la plus populaire a fonctionné le mieux pour moi et est le plus simple. Je le republie ici pour le rendre plus évident pour les futurs utilisateurs.)

19
WxGuy

Comme Vicky l’a déjà fait remarquer, %DATE% et %TIME% renvoient la date et l’heure actuelles en utilisant les formats de date et d’heure courts qui sont entièrement (indéfiniment) personnalisables.

Un utilisateur peut configurer son système pour qu'il retourne Fri040811 08.03 heures, tandis qu'un autre utilisateur peut choisir le 08/04/2011 20:30.

C'est un cauchemar complet pour un programmeur BAT.

Changer le format en un format ferme peut résoudre le problème, à condition que vous restauriez le format précédent avant de quitter le fichier BAT. Mais il peut être sujet à de mauvaises conditions de course et compliquer la récupération des fichiers BAT annulés.

Heureusement, il y a une alternative.

Vous pouvez utiliser WMIC à la place. WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table renvoie la date et l'heure d'une manière invariable. Très pratique pour l’analyser directement avec une commande FOR /F.

Alors, assemblant les pièces, essayez ceci comme point de départ ...

SETLOCAL enabledelayedexpansion
FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
  SET /A FD=%%F*1000000+%%D*100+%%A
  SET /A FT=10000+%%B*100+%%C
  SET FT=!FT:~-4!
  ECHO Archive_!FD!_!FT!.Zip
 )
14
PA.

J'ai trouvé la meilleure solution pour moi, après avoir lu toutes vos réponses:

set t=%date%_%time%
set d=%t:~10,4%%t:~7,2%%t:~4,2%_%t:~15,2%%t:~18,2%%t:~21,2%
echo hello>"Archive_%d%"

Si AM je reçois 20160915_ 150101 (avec un espace et un temps de premier plan).

Si PM j'obtiens 20160915_2150101.

8
Nesar

Vous pouvez ajouter des zéros au début d'une variable (valeur jusqu'à 99) comme celle-ci en batch: IF 1%Var% LSS 100 SET Var=0%Var%

Vous devez donc analyser vos composants de date et d’heure dans des variables distinctes, les traiter tous comme ceci, puis les concaténer pour créer le nom du fichier.

Cependant, votre méthode sous-jacente d'analyse de la date et de l'heure dépend des paramètres régionaux du système. Si vous préférez que votre code ne soit pas portable sur d'autres machines, c'est probablement bien, mais si vous vous attendez à ce qu'il fonctionne dans différents contextes internationaux, vous aurez besoin d'une approche différente, par exemple en lisant les paramètres de registre:

HKEY_CURRENT_USER\Control Panel\International\iDate
HKEY_CURRENT_USER\Control Panel\International\iTime
HKEY_CURRENT_USER\Control Panel\International\iTLZero

(Ce dernier contrôle s'il existe un zéro non significatif, mais pas les dates pour autant que je sache). 

4
Vicky
@For /F "tokens=1,2,3,4 delims=/ " %%A in ('Date /t') do @(

Set DayW=%%A

Set Day=%%B

Set Month=%%C


Set Year=%%D


Set All=%%D%%B%%C
)
"C:\Windows\CWBZIP.EXE" "c:\transfer\ziptest%All%.Zip" "C:\transfer\MB5L.txt"

Cela prend MB5L.txt et le compresse en ziptest20120204.Zip si exécuté le 4 février 2012

3
user1189773

Votre question semble être résolue, mais ...

Je ne sais pas si vous prenez la bonne solution à votre problème.
Je suppose que vous essayez de compresser chaque jour le code du projet.

C'était possible avec Zip et 1980, c'était une bonne solution, mais aujourd'hui, vous devriez utiliser un système de référentiel, comme Subversion ou git ou ..., mais pas un fichier Zip.

Ok, peut-être que je me trompe peut-être.

2
jeb

D'après la réponse ci-dessus, j'ai créé une fonction prête à l'emploi.

Validé avec les paramètres locaux français.

:::::::: PROGRAM ::::::::::

call:genname "my file 1.txt"
echo "%newname%"
call:genname "my file 2.doc"
echo "%newname%"

echo.&pause&goto:eof
:::::::: FUNCTIONS :::::::::

:genname
    set d1=%date:~-4,4%
    set d2=%date:~-10,2%
    set d3=%date:~-7,2%
    set t1=%time:~0,2%
    ::if "%t1:~0,1%" equ " " set t1=0%t1:~1,1%
    set t1=%t1: =0%
    set t2=%time:~3,2%
    set t3=%time:~6,2%
    set filename=%~1
    set newname=%d1%%d2%%d3%_%t1%%t2%%t3%-%filename%
goto:eof
2
user2757848

Je me rends compte que c’est une question discutable pour le PO, mais je viens de la préparer, et je suis un peu fière de moi pour avoir su sortir des sentiers battus.

Téléchargez gawk pour Windows à l’adresse http://gnuwin32.sourceforge.net/packages/gawk.htm .... Il s’agit alors d’une couche unique, sans toute la syntaxe de traitement par lots DOS, FOR boucles pour séparer les cordes (WTF? C'est vraiment vraiment MAUVAIS MAD ET SAD! ... à mon humble avis, bien sûr)

Si vous connaissez déjà C, C++, Perl ou Ruby, alors ramasser AWK (qui hérite des deux précédentes et contribue de manière significative aux deux dernières) est un morceau du gâteau CAKE !!!

La commande batch DOS:

echo %DATE% %TIME% && echo %DATE% %TIME% | gawk -F"[ /:.]" "{printf(""""%s%02d%02d-%02d%02d%02d\n"""", $4, $3, $2, $5, $6, $7);}"

Prints:

Tue 04/09/2012 10:40:38.25
20120904-104038

Maintenant, ce n'est pas tout à fait l'histoire ... Je vais simplement être paresseux et coder en dur le reste de mon nom de fichier journal dans la déclaration printf, parce que c'est simple ... Mais si quelqu'un sait comment définir une % NOW% variable à la sortie de AWK (yeilding les entrailles d'une fonction "générique" maintenant) alors je suis tout ouïe.


MODIFIER:

Une recherche rapide sur Stack Overflow a rempli cette dernière pièce du puzzle, Équivalent par lots de Bash backticks _.

Donc, ces trois lignes de lot DOS:

echo %DATE% %TIME% | awk -F"[ /:.]" "{printf(""""%s%02d%02d-%02d%02d%02d\n"""", $4, $3, $2, $5, $6, $7);}" >%temp%\now.txt
set /p now=<%temp%\now.txt
echo %now%

Produire:

20120904-114434

Alors maintenant, je peux inclure une date/heure dans le nom du fichier journal généré par mon script d'installation (2005+) de SQL Server:

sqlcmd -S .\SQLEXPRESS -d MyDb -e -i MyTSqlCommands.sql >MyTSqlCommands.sql.%now%.log

Et je suis de nouveau un campeur heureux (sauf que la vie était encore tellement plus facile sur Unix).

0
corlettk

Comme d'autres l'ont déjà fait remarquer, les formats de date et d'heure de %DATE% et %TIME% (ainsi que date /T et time /T) dépendent de la localisation, ce qui permet d'extraire la date actuelle. et le temps est toujours un cauchemar, et il est impossible de trouver une solution qui fonctionne avec tous les formats possibles, car il n’ya pratiquement aucune limitation de formats.


Mais il y a un autre problème avec un code comme le suivant (supposons un format de date tel que MM/DD/YYYY et un format horaire de 12 h tel que h:mm:ss.ff apap est soit AM. ou PM et ff sont des fractions de secondes):

rem // Resolve AM/PM time:
set "HOUR=%TIME:~,2%"
if "%TIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%TIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %DATE:~-4,4%%DATE:~0,2%%DATE:~3,2%_%HOUR:~-2%%TIME:~3,2%%TIME:~6,2%

Chaque instance de %DATE% et %TIME% renvoie la valeur de date ou d'heure présente au moment de son expansion. Par conséquent, la première expression %DATE% ou %TIME% peut renvoyer une valeur différente de celle suivants (vous pouvez prouver que lorsque vous répétez une longue chaîne contenant une quantité énorme de telles expressions, de préférence %TIME%, expressions).

Vous pouvez améliorer le code susmentionné pour qu'il ne contienne qu'une seule instance de %DATE% et %TIME% comme ceci:

rem // Store current date and time once in the same line:
set "CURRDATE=%DATE%" & set "CURRTIME=%TIME%"
rem // Resolve AM/PM time:
set "HOUR=%CURRTIME:~,2%"
if "%CURRTIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%CURRTIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %CURRDATE:~-4,4%%CURRDATE:~0,2%%CURRDATE:~3,2%_%HOUR:~-2%%CURRTIME:~3,2%%CURRTIME:~6,2%

Néanmoins, les valeurs renvoyées dans %DATE% et %TIME% peuvent refléter des jours différents lorsqu’elles sont exécutées à minuit.

La seule façon d'avoir le même jour dans %CURRDATE% et %CURRTIME% est la suivante:

rem // Store current date and time once in the same line:
set "CURRDATE=%DATE%" & set "CURRTIME=%TIME%"
rem // Resolve AM/PM time:
set "HOUR=%CURRTIME:~,2%"
if "%CURRTIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%CURRTIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Fix date/time midnight discrepancy:
if not "%CURRDATE%" == "%DATE%" if %CURRTIME:~0,2% equ 0 set "CURRDATE=%DATE%"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %CURRDATE:~-4,4%%CURRDATE:~0,2%%CURRDATE:~3,2%_%HOUR:~-2%%CURRTIME:~3,2%%CURRTIME:~6,2%

Bien sûr, l’apparition du problème décrit est assez improbable, mais à un moment donné, cela se produira et provoquera d’étranges échecs inexplicables.


Le problème décrit ne peut pas se produire avec les approches basées sur la commande wmic comme décrit dans le réponse par l'utilisateur Stephan et dans le réponse par l'utilisateur PA. , je vous recommande donc fortement de choisir l'un d'entre eux. Le seul inconvénient de wmic est qu’il est beaucoup plus lent.

0
aschipfl

Un espace est légal dans les noms de fichiers. Si vous mettez votre chemin et votre nom de fichier entre guillemets, cela risque de voler. Voici ce que j'utilise dans un fichier batch:

svnadmin hotcopy "C:\SourcePath\Folder" "f:\DestPath\Folder%filename%"

Peu importe s'il y a des espaces dans% filename%. 

0
Marty