Création d'un nom de fichier comme horodatage dans un travail par lots

90

Nous avons un travail par lots qui s'exécute tous les jours et copie un fichier dans un dossier de collecte. Je veux également prendre une copie de ce fichier et le déposer dans un dossier d'archive avec le nom de fichier

 yyyy-MM-dd.log

Quelle est la façon la plus simple de faire cela dans un travail par lots Windows?

Je recherche essentiellement un équivalent de cette commande Unix:

cp source.log `date +%F`.log
Eoin Campbell
la source
Lorsque vous obtenez une chaîne de date au format souhaité dans les fichiers Windows .bat, cela semble aussi mauvais que les solutions proposées. Honnêtement, vérifiez simplement quels langages de programmation sont disponibles sur la machine, par exemple java, ruby, perl ou autre chose, et créez un exécutable de 5 secondes pour vous donner ce que vous voulez. Je ne perdrais pas de temps à maintenir un fichier .bat qui nécessite plus d'une ligne de code pour obtenir une date avec un format approprié.
99Sono

Réponses:

105
CP source.log %DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%.log

Mais cela dépend de la localisation. Je ne sais pas si %DATE%est localisé ou dépend du format spécifié pour la date courte dans Windows.

Voici un moyen indépendant de la langue pour extraire la date actuelle de cette réponse , mais cela dépend de WMICet FOR /F:

FOR /F %%A IN ('WMIC OS GET LocalDateTime ^| FINDSTR \.') DO @SET B=%%A
CP source.log %B:~0,4%-%B:~4,2%-%B:~6,2%.log
opello
la source
6
Il fallait faire un peu de bidouillage avec les indices, mais cela semble avoir fait l'affaire. (mais je ne suis pas tout à fait sûr de comprendre la logique de l'index moins)% DATE: ~ -4% -% DATE: ~ -7, -5% -% DATE: ~ -10, -8% .log
Eoin Campbell
1
Si vous souhaitez utiliser tous les indices positifs, vous pouvez utiliser:% DATE: ~ 10,4% -% DATE: ~ 4,2% -% DATE: ~ 7,2%
opello
(Je viens de prendre cela à partir de quelque chose d'autre sur lequel j'avais travaillé, c'était il y a longtemps, et je ne sais pas pourquoi je l'ai fait comme je l'ai fait à l'origine, heh.)
opello
3
Cela ne fonctionne pas sur d'autres paramètres régionaux. Dans mon cas, la commande revient 2014-5.-01(quand elle le serait 2014-05-26). Soyez donc très prudent, si vous publiez des scripts contenant cela!
amenthes
5
Utilisez ceci pour le temps (supprime les millisecondes): %time:~-11,2%-%time:~-8,2%-%time:~-5,2%
MRC
48

Cela a fonctionné pour moi et était une solution sûre pour les noms de fichiers (bien qu'elle génère un format MM-jj-AAAA):

C:\ set SAVESTAMP=%DATE:/=-%@%TIME::=-%
C:\ set SAVESTAMP=%SAVESTAMP: =%
C:\ set SAVESTAMP=%SAVESTAMP:,=.%.jpg
C:\ echo %SAVESTAMP%
[email protected]

La première commande prend une DATE et remplace /par -, prend le TIME et remplace :par -, et les combine au format DATE @ TIME. La deuxième setinstruction supprime tous les espaces et la troisième setremplace, par .et ajoute l' .jpgextension.

Le code ci-dessus est utilisé dans un petit script qui extrait des images d'une caméra IP de sécurité pour un traitement ultérieur:

:while
set SAVESTAMP=%DATE:/=-%@%TIME::=-%
set SAVESTAMP=%SAVESTAMP: =%
set SAVESTAMP=%SAVESTAMP:,=.%.jpg
wget-1.10.2.exe --tries=0 -O %SAVESTAMP% http://admin:<password>@<ip address>:<port>/snapshot.cgi
timeout 1
GOTO while
Daniel Sokolowski
la source
la sortie sur ma console est 10-12-2014@14-22-59,44.jpgavec une virgule avant les millisecondes
BeNdErR
1
Essayez d'ajouter set SAVESTAMP=%SAVESTAMP:,=.%.jpgavant l' echoinstruction. Si cela fonctionne, je mettrai à jour la réponse.
Daniel Sokolowski
1
Ce n'est pas indépendant des paramètres régionaux. Retours 08.06.2016@15-42-20,33.jpgsur mon ordinateur portable allemand et [email protected]sur mon ordinateur anglais.
Hannobo
5
Mais ce n'est toujours ni indépendant des paramètres régionaux ni ne crée le format (iso8601) correct deyyyy-MM-dd
jeb
1
C'est ennuyeux que la première ligne prétende toujours qu'elle était indépendante de la locale, juste pour voir que ce n'est pas après avoir essayé ...
m3tikn0b
16

Pour les paramètres régionaux français (France) UNIQUEMENT , soyez prudent car /apparaît dans la date:

echo %DATE%
08/09/2013

Pour notre problème de fichier journal, voici ma proposition pour la langue française UNIQUEMENT :

SETLOCAL
set LOGFILE_DATE=%DATE:~6,4%.%DATE:~3,2%.%DATE:~0,2%
set LOGFILE_TIME=%TIME:~0,2%.%TIME:~3,2%
set LOGFILE=log-%LOGFILE_DATE%-%LOGFILE_TIME%.txt
rem log-2014.05.19-22.18.txt
command > %LOGFILE%
Aubin
la source
Excellent! Un peu difficile à lire, mais cela permet de formater la sortie comme vous le souhaitez.
davitof
2
Super mais soyez prudent si vous voulez éviter les caractères blancs car HOUR peut être à 1 chiffre rendu comme ça: "_0:00"(le caractère souligné est un espace)
daVe
1
J'obtiens "log- / 18 /. 0.Sa- 9.16.txt" pour cette réponse.
ledlogic
@ledlogic: quelle est votre localisation? Cette réponse concerne les paramètres régionaux français.
Aubin
1
Ne fonctionne PAS Je reçois ceci sur Windows 7 - log- / 05 /. 0.We-18.13.tx
Sam B
10

Voici une solution indépendante des paramètres régionaux (copie dans un fichier nommé SetDateTimeComponents.cmd):

@echo off
REM This script taken from the following URL:
REM http://www.winnetmag.com/windowsscripting/article/articleid/9177/windowsscripting_9177.html

REM Create the date and time elements.
for /f "tokens=1-7 delims=:/-, " %%i in ('echo exit^|cmd /q /k"prompt $d $t"') do (
   for /f "tokens=2-4 delims=/-,() skip=1" %%a in ('echo.^|date') do (
      set dow=%%i
      set %%a=%%j
      set %%b=%%k
      set %%c=%%l
      set hh=%%m
      set min=%%n
      set ss=%%o
   )
)

REM Let's see the result.
echo %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss%

J'ai mis tous mes scripts .cmd dans le même dossier (% SCRIPTROOT%); tout script nécessitant des valeurs de date / heure appellera SetDateTimeComponents.cmd comme dans l'exemple suivant:

setlocal

@echo Initializing...
set SCRIPTROOT=%~dp0
set ERRLOG=C:\Oopsies.err

:: Log start time
call "%SCRIPTROOT%\SetDateTimeComponents.cmd" >nul
@echo === %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss% : Start === >> %ERRLOG%

:: Perform some long running action and log errors to ERRLOG.

:: Log end time
call "%SCRIPTROOT%\SetDateTimeComponents.cmd" >nul
@echo === %dow% %yy%-%mm%-%dd% @ %hh%:%min%:%ss% : End === >> %ERRLOG%

Comme le montre l'exemple, vous pouvez appeler SetDateTimeComponents.cmd chaque fois que vous avez besoin de mettre à jour les valeurs de date / heure. Cacher le script d'analyse temporelle dans son propre fichier SetDateTimeComponents.cmd est un bon moyen de cacher les détails laids et, plus important encore, d'éviter les fautes de frappe.

totorocat
la source
2
désolé, ce n'est pas indépendant des paramètres régionaux: sur mon Windows français, j'obtiens "18 -2014- @ 13:14:43"
davitof
1
Peut confirmer: pas indépendant des paramètres régionaux. prompt $d $trenvoie 30.05.2016 15: 35: 56,93 sur mon système.
Hannobo
7

Parce que l'idée de les déchirer %DATE%et de les %TIME%séparer et de les écraser semble au mieux fragile, voici une alternative qui utilise un oneliner PowerShell:

for /f %i in ('powershell -c "get-date -format yyyy-MM-dd--HH-mm-ss"') do @set DATETIME=%i
set LOGFILE=my-script-%DATETIME%.txt

La référence pour get-dateest ici , avec des options de format pour les styles .NET et UNIX.

tboz203
la source
6

J'utilise fréquemment ceci et mets tout dans une commande de copie unique. L'exemple suivant copie le fichier example.txt sous le nom example_YYYYMMDD_HHMMSS.txt et vous pouvez bien sûr le modifier en fonction de votre format préféré. Les guillemets ne sont nécessaires que s'il y a des espaces dans la spécification de fichier. Si vous souhaitez réutiliser exactement la même date / horodatage, vous devez le stocker dans une variable.

copy "{path}\example.txt" "{path}\_%date:~10,4%%date:~4,2%%date:~7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.txt"
BeConcise
la source
6

Cela garantira que la sortie est une valeur à 2 chiffres ... vous pouvez réorganiser la sortie à votre guise et tester en supprimant les commentaires de la section de diagnostic. Prendre plaisir!

(J'en ai beaucoup emprunté à d'autres forums ...)

:: ------------------ Date and Time Modifier ------------------------

@echo off
setlocal

:: THIS CODE WILL DISPLAY A 2-DIGIT TIMESTAMP FOR USE IN APPENDING FILENAMES

:: CREATE VARIABLE %TIMESTAMP%

for /f "tokens=1-8 delims=.:/-, " %%i in ('echo exit^|cmd /q /k"prompt $D $T"') do (
   for /f "tokens=2-4 skip=1 delims=/-,()" %%a in ('echo.^|date') do (
set dow=%%i
set %%a=%%j
set %%b=%%k
set %%c=%%l
set hh=%%m
set min=%%n
set sec=%%o
set hsec=%%p
)
)

:: ensure that hour is always 2 digits

if %hh%==0 set hh=00
if %hh%==1 set hh=01
if %hh%==2 set hh=02
if %hh%==3 set hh=03
if %hh%==4 set hh=04
if %hh%==5 set hh=05
if %hh%==6 set hh=06
if %hh%==7 set hh=07
if %hh%==8 set hh=08
if %hh%==9 set hh=09


:: --------- TIME STAMP DIAGNOSTICS -------------------------

:: Un-comment these lines to test output

:: echo dayOfWeek = %dow%
:: echo year = %yy%
:: echo month = %mm%
:: echo day = %dd%
:: echo hour = %hh%
:: echo minute = %min%
:: echo second = %sec%
:: echo hundredthsSecond = %hsec%
:: echo.
:: echo Hello! 
:: echo Today is %dow%, %mm%/%dd%. 
:: echo.
:: echo. 
:: echo.
:: echo.
:: pause

:: --------- END TIME STAMP DIAGNOSTICS ----------------------

:: assign timeStamp:
:: Add the date and time parameters as necessary - " yy-mm-dd-dow-min-sec-hsec "

endlocal & set timeStamp=%yy%%mm%%dd%_%hh%-%min%-%sec%
echo %timeStamp%
Rick Rubino
la source
2

Créez un fichier avec la date actuelle comme nom de fichier (ex. 2008-11-08.dat)

echo hello > %date%.dat    

Avec la date actuelle mais sans le "-" (ex. 20081108.dat)

echo hello > %date:-=%.dat   
RealHowTo
la source
2

Peut-être que cela peut aider:

echo off
@prompt set date=$d$_ set time=$t$h$h$h
echo some log >> %date% %time%.log
exit

ou

echo off
set v=%date%.log
echo some log >> %v%
Secko
la source
Nice one Secko ... cette valeur% date% semble avoir ce que je recherche. Toute chance, vous pouvez expliquer l'instruction SET. Que sont exactement $ d $ _set & $ t $ h $ h $ h
Eoin Campbell
1
set est une instruction "SET variable". Où la variable de date est $ d $ _ (jour + le reste) et la variable d'heure est $ t $ h $ h $ h (heure + ms). J'ai essayé de montrer comment cela peut être fait avec un ensemble de variables, cela peut fonctionner correctement sans la ligne d'invite. J'ai essentiellement essayé de faire ce set date =% YYYY %% MM %% DD% mais j'exécute Linux ici et je compile le script sur SciTE donc je ne sais pas si cela fonctionne. Désolé si ça ne marche pas.
Secko
J'ai oublié d'ajouter, $ _ est une nouvelle ligne.
Secko
1
Essayez aussi, @prompt // $ d $ _ $ t $ h $ h $ h $ h $ h $ h //
Secko
Notez que ce n'est pas non plus indépendant des paramètres régionaux. La date est mise en forme selon le paramètre de culture actuel, dans mon cas DD.MM.YYYY (pour l'allemand).
Hannobo
2

J'ai mis en place un petit programme C pour imprimer l'horodatage actuel (sécurité locale, pas de mauvais caractères ...). Ensuite, j'utilise la commande FOR pour enregistrer le résultat dans une variable d'environnement:

:: Get the timestamp
for /f %%x in ('@timestamp') do set TIMESTAMP=%%x

:: Use it to generate a filename
for /r %%x in (.\processed\*) do move "%%~x" ".\archived\%%~nx-%TIMESTAMP%%%~xx"

Voici un lien:

https://github.com/HarryPehkonen/dos-timestamp

Harry Pehkonen
la source
2

Je sais que ce fil est vieux mais je veux juste ajouter ceci ici car cela m'a beaucoup aidé à essayer de comprendre tout cela et c'est propre. La bonne chose à ce sujet est que vous pouvez le mettre en boucle pour un fichier de commandes toujours en cours d'exécution. Journal de disponibilité du serveur ou quelque chose. C'est pour ça que je l'utilise de toute façon. J'espère que cela aidera quelqu'un un jour.

@setlocal enableextensions enabledelayedexpansion
@echo off

call :timestamp freshtime freshdate
echo %freshdate% - %freshtime% - Some data >> "%freshdate - Somelog.log"

:timestamp
set hour=%time:~0,2%
if "%hour:~0,1%" == " " set hour=0%hour:~1,1%
set min=%time:~3,2%
if "%min:~0,1%" == " " set min=0%min:~1,1%
set secs=%time:~6,2%
if "%secs:~0,1%" == " " set secs=0%secs:~1,1%
set FreshTime=%hour%:%min%:%secs%

set year=%date:~-4%
set month=%date:~4,2%
if "%month:~0,1%" == " " set month=0%month:~1,1%
set day=%date:~7,2%
if "%day:~0,1%" == " " set day=0%day:~1,1%
set FreshDate=%month%.%day%.%year%
Haxslie
la source
Cela m'a été utile, bien que dans un fichier ".cmd", les deux points de la variable "FreshTime" provoquaient des erreurs lorsqu'ils étaient utilisés pour un nom de fichier dans ma cmdline "robocopy": ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"Comme correctif, j'ai utilisé des tirets à la place:set FreshTime=%hour%-%min%-%secs%
netdesignate
2

Vous pouvez simplement détecter le format local actuel et obtenir la date dans votre format, par exemple:

::for 30.10.2016 dd.MM.yyyy
if %date:~2,1%==. set d=%date:~-4%%date:~3,2%%date:~,2%
::for 10/30/2016 MM/dd/yyyy
if %date:~2,1%==/ set d=%date:~-4%%date:~,2%%date:~3,2%
::for 2016-10-30 yyyy-MM-dd
if %date:~4,1%==- set d=%date:~,4%%date:~5,2%%date:~-2%
::variable %d% have now value: 2016103 (yyyyMMdd)
set t=%time::=%
set t=%t:,=%
::variable %t% have now time without delimiters
cp source.log %d%_%t%.log
Adam Silenko
la source
2

Je sais que c'est un ancien message, mais il y a une réponse beaucoup plus simple (même si cela ne fonctionne peut-être que dans les nouvelles versions de Windows). Utilisez simplement le paramètre / t pour les commandes DATE et TIME dos pour afficher uniquement la date ou l'heure et ne pas vous inviter à le définir, comme ceci:

@echo off
echo Starting test batch file > testlog.txt
date /t >> testlog.txt
time /t >> testlog.txt
doyen
la source
1

1) Vous pouvez télécharger GNU coreutils qui est livré avec la date GNU

2) vous pouvez utiliser VBScript , ce qui facilite la manipulation de la date sous Windows:

Set objFS = CreateObject("Scripting.FileSystemObject")
strFolder = "c:\test"
Set objFolder = objFS.GetFolder(strFolder)
current = Now
mth = Month(current)
d = Day(current)
yr = Year(current)
If Len(mth) <2 Then
    mth="0"&mth
End If
If Len(d) < 2 Then
    d = "0"&d
End If
timestamp=yr & "-" & mth &"-"& d
For Each strFile In objFolder.Files
    strFileName = strFile.Name
    If InStr(strFileName,"file_name_here") > 0 Then
        BaseName = objFS.GetBaseName(strFileName)
        Extension = objFS.GetExtensionName(strFileName)
        NewName = BaseName & "-" & timestamp & "." & Extension
        strFile.Name = NewName
    End If
Next

Exécutez le script en tant que:

c:\test> cscript /nologo myscript.vbs
ghostdog74
la source
0

Cela fonctionne bien avec (ma) langue allemande, devrait être possible de l'ajuster à vos besoins ...

forfiles /p *PATH* /m *filepattern* /c "cmd /c ren @file 
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_@file"
Martin
la source
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%fonctionne aussi pour l'emplacement portugais! Je veux dire AAAAMMJJ
Fernando Fabreti
0

Pour les gros fichiers zip pour le déploiement, j'utilise des quarts d'heure. Personne d'autre sur cette page ne l'avait mentionné auparavant, je vais donc mettre mon petit script ici:

set /a "quarter_hours=%time:~0,2%*4 + %time:~3,2% / 15"
set "zip_file=release_%DATE:~-4%.%DATE:~4,2%.%DATE:~7,2%.%quarter_hours%.zip"

Il ne met pas encore à zéro les quarts d'heure de minuit à 5 heures du matin, mais cela vous permet toujours d'avoir une version tamponnée plusieurs fois par jour avec peu de collisions.

J'espère que cela pourra aider.

phyatt
la source
0

a utilisé la suggestion de Martin avec un petit ajustement pour ajouter un horodatage au nom du fichier:

forfiles /p [foldername] /m rsync2.log /c "cmd /c ren @file %DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_%time:~-11,2%-%time:~-8,2%-%time:~-5,2%-@file

Pour le 10:17:21 23/10/2019 Le résultat est:

20191023_10-17-21-rsync2.log

Gennady Sorochan
la source