Creazione di un nome file come timestamp in un lavoro batch


90

Abbiamo un lavoro batch che viene eseguito ogni giorno e copia un file in una cartella di prelievo. Voglio anche prendere una copia di quel file e rilasciarlo in una cartella di archivio con il nome del file

 yyyy-MM-dd.log

Qual è il modo più semplice per farlo in un lavoro batch di Windows?

Fondamentalmente sto cercando un equivalente di questo comando Unix:

cp source.log `date +%F`.log

Quando si ottiene una stringa di data con il formato desiderato nei file .bat di Windows, sembra pessimo quanto le soluzioni proposte. Onestamente, controlla solo quali linguaggi di programmazione sono disponibili sulla macchina, ad esempio java, ruby, perl o qualcos'altro, e crea un eseguibile di 5 secondi per darti quello che vuoi. Non perderei tempo a mantenere il file .bat che richiede più di una riga di codice per ottenere una data con un formato appropriato.
99Sono

Risposte:


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

Ma dipende dalla località. Non sono sicuro che %DATE%sia localizzato o dipenda dal formato specificato per la data breve in Windows.

Ecco un modo indipendente dalle impostazioni locali per estrarre la data corrente da questa risposta , ma dipende da WMICe 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

6
Avevo bisogno di giocherellare un po 'con gli indici, ma questo sembra aver funzionato. (anche se non sono completamente sicuro di aver compreso la logica dell'indice negativo)% DATE: ~ -4% -% DATE: ~ -7, -5% -% DATE: ~ -10, -8% .log
Eoin Campbell

1
Se si desidera utilizzare tutti gli indici positivi, è possibile utilizzare:% DATE: ~ 10,4% -% DATE: ~ 4,2% -% DATE: ~ 7,2%
opello

(L'ho appena preso da qualcos'altro su cui avevo lavorato, è stato molto tempo fa, e non ho idea del motivo per cui l'ho fatto nel modo in cui l'ho fatto originariamente,
eh

3
Questo si interrompe in altri luoghi. Nel mio caso il comando ritorna 2014-5.-01(quando sarebbe 2014-05-26). Quindi stai molto attento, se pubblichi script che contengono questo!
amenthes

5
Usa questo per il tempo (rimuove i millisecondi): %time:~-11,2%-%time:~-8,2%-%time:~-5,2%
MRC

48

Questo ha funzionato per me ed era una soluzione sicura per i nomi di file (sebbene generi un formato MM-gg-AAAA):

C:\ set SAVESTAMP=%DATE:/=-%@%TIME::=-%
C:\ set SAVESTAMP=%SAVESTAMP: =%
C:\ set SAVESTAMP=%SAVESTAMP:,=.%.jpg
C:\ echo %SAVESTAMP%
11-04-2012@20-52-42.79.jpg

Il primo comando prende una DATA e la sostituisce /con -, prende l'ora e la sostituisce :con -e le combina nel formato DATE @ TIME. La seconda setdichiarazione rimuove tutti gli spazi, e il terzo setsostituisce ,con .e aggiunge il .jpgprolungamento.

Il codice sopra viene utilizzato in un piccolo script che estrae le immagini da una telecamera IP di sicurezza per ulteriori elaborazioni:

: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

l'output sulla mia console è 10-12-2014@14-22-59,44.jpgcon una virgola prima dei millisecondi
BeNdErR

1
Prova ad aggiungere set SAVESTAMP=%SAVESTAMP:,=.%.jpgprima della echodichiarazione. Se funziona aggiornerò la risposta.
Daniel Sokolowski

1
Questo non è indipendente dalle impostazioni locali. Ritorna 08.06.2016@15-42-20,33.jpgsul mio portatile tedesco e Wed06-08-2016@15-43-45.89.jpgsu quello inglese.
Hannobo

5
Ma non è ancora indipendente dalla locale né crea il formato corretto (iso8601) diyyyy-MM-dd
jeb

1
È fastidioso che la prima riga affermi ancora che era indipendente dalla locale, solo per vedere che non è dopo aver provato ...
m3tikn0b

16

SOLO per le impostazioni internazionali francesi (Francia) , fare attenzione perché /appare nella data:

echo %DATE%
08/09/2013

Per il nostro problema di file di registro, ecco la mia proposta SOLO per le impostazioni internazionali francesi :

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%

Eccellente! Un po 'difficile da leggere, ma consente di formattare l'output proprio come si desidera.
davitof

2
Ottimo ma fai attenzione se vuoi evitare i caratteri bianchi perché HOUR può essere 1 cifra resa così: "_0:00"(il carattere di sottolineatura è uno spazio)
daVe

1
Ottengo "log- / 18 /. 0.Sa- 9.16.txt" per questa risposta.
ledlogic

@ledlogic: qual è il tuo locale? Questa risposta è per la lingua francese.
Aubin

1
NON funziona, ottengo questo su Windows 7 - log- / 05 /. 0.We-18.13.tx
Sam B

10

Ecco una soluzione indipendente dalla locale (copia in un file denominato 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%

Ho messo tutti i miei script .cmd nella stessa cartella (% SCRIPTROOT%); qualsiasi script che necessita di valori di data / ora chiamerà SetDateTimeComponents.cmd come nell'esempio seguente:

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%

Come mostra l'esempio, puoi chiamare SetDateTimeComponents.cmd ogni volta che devi aggiornare i valori di data / ora. Nascondere lo script di analisi del tempo nel proprio file SetDateTimeComponents.cmd è un bel modo per nascondere i dettagli orribili e, soprattutto, evitare errori di battitura.


2
scusa, non è indipendente dalla locale: sul mio Windows francese, ottengo "18 -2014- @ 13:14:43"
davitof

1
Può confermare: non indipendente dalla locale. prompt $d $trestituisce 30.05.2016 15: 35: 56,93 sul mio sistema.
Hannobo

7

Poiché l'idea di strapparli %DATE%e %TIME%separarli e schiacciarli insieme sembra fragile nel migliore dei casi, ecco un'alternativa che utilizza 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

Il riferimento per get-dateè qui , con opzioni di formato sia per lo stile .NET che per lo stile UNIX.


6

Lo uso spesso e metto tutto in un unico comando di copia. Il seguente copia example.txt come example_YYYYMMDD_HHMMSS.txt e ovviamente puoi modificarlo per adattarlo al tuo formato preferito. Le virgolette sono necessarie solo se sono presenti spazi nel filespec. Se desideri riutilizzare la stessa identica data / ora, devi memorizzarla in una variabile.

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

6

Ciò garantirà che l'output sia un valore a 2 cifre ... puoi riorganizzare l'output a tuo piacimento e testare annullando i commenti nella sezione diagnostica. Godere!

(Ho preso in prestito molto di questo da altri forum ...)

:: ------------------ 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%

2

Crea un file con la data corrente come nome file (es. 2008-11-08.dat)

echo hello > %date%.dat    

Con la data corrente ma senza il "-" (es. 20081108.dat)

echo hello > %date:-=%.dat   

2

Forse questo può aiutare:

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

o

echo off
set v=%date%.log
echo some log >> %v%

Simpatico Secko ... quel valore% date% sembra avere quello che sto cercando. Qualsiasi possibilità tu possa spiegare l'istruzione SET. Cosa sono esattamente $ d $ _set e $ t $ h $ h $ h
Eoin Campbell,

1
set è un'istruzione "SET variable". Dove la variabile data è $ d $ _ (giorno + il resto) e la variabile tempo è $ t $ h $ h $ h (ora + ms). Ho provato a mostrare come può essere fatto con un insieme di variabili può funzionare bene senza la riga di prompt. Fondamentalmente ho provato a fare questa data impostata =% YYYY %% MM %% DD% ma sto eseguendo Linux qui e compilando lo script su SciTE, quindi non so se funziona. Scusa se non funziona.
Secko

Ho dimenticato di aggiungere, $ _ è una nuova riga.
Secko

1
Prova anche, @prompt // $ d $ _ $ t $ h $ h $ h $ h $ h $ h //
Secko

Notare che anche questo non è indipendente dalla locale. La data è formattata in base all'impostazione della cultura corrente, nel mio caso GG.MM.AAAA (per il tedesco).
Hannobo

2

Ho messo insieme un piccolo programma in C per stampare il timestamp corrente (locale sicuro, nessun cattivo carattere ...). Quindi, utilizzo il comando FOR per salvare il risultato in una variabile di ambiente:

:: 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"

Ecco un collegamento:

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


2

So che questo thread è vecchio ma voglio solo aggiungerlo qui perché mi ha aiutato molto a cercare di capire tutto ed è pulito. La cosa bella di questo è che potresti metterlo in un ciclo per un file batch sempre in esecuzione. Registro dei tempi di attività del server o qualcosa del genere. È per questo che lo uso comunque. Spero che questo aiuti qualcuno un giorno.

@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%

Questo è stato utile per me, sebbene in un file ".cmd", i due punti nella variabile "FreshTime" causassero errori quando venivano usati per un nome di file nella mia riga "robocopy": ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"come correzione ho usato invece i trattini:set FreshTime=%hour%-%min%-%secs%
netdesignate

2

Puoi semplicemente rilevare il formato locale corrente e ottenere la data nel tuo formato, ad esempio:

::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

2

So che questo è un vecchio post, ma c'è una risposta molto più semplice (anche se forse funziona solo nelle versioni più recenti di Windows). Usa semplicemente il parametro / t per i comandi DATE e TIME dos per mostrare solo la data o l'ora e non chiederti di impostarla, in questo modo:

@echo off
echo Starting test batch file > testlog.txt
date /t >> testlog.txt
time /t >> testlog.txt

1

1) Puoi scaricare GNU coreutils fornito con GNU date

2) puoi usare VBScript , che semplifica la manipolazione della data in 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

Esegui lo script come:

c:\test> cscript /nologo myscript.vbs

0

Funziona bene con la (mia) lingua tedesca, dovrebbe essere possibile adattarla alle tue esigenze ...

forfiles /p *PATH* /m *filepattern* /c "cmd /c ren @file 
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_@file"

%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%funziona anche per località portoghesi! Intendo AAAAMMGG
Fernando Fabreti

0

Per i file zip di grandi dimensioni per la distribuzione, utilizzo i quarti d'ora. Nessun altro in questa pagina ne aveva parlato prima, quindi inserirò il mio piccolo script qui:

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"

Non è ancora azzerato il quarto d'ora da mezzanotte alle 5 del mattino, ma lo fa comunque in modo da poter avere un rilascio timbrato più volte al giorno con poche collisioni.

Spero che aiuti.


0

ha usato il suggerimento di Martin con un piccolo aggiustamento per aggiungere il timestamp al nome del file:

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

Per il 23/10/2019 10:17:21 Il risultato è:

20191023_10-17-21-rsync2.log

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.