Erstellen eines Dateinamens als Zeitstempel in einem Stapeljob


90

Wir haben einen Stapeljob, der jeden Tag ausgeführt wird und eine Datei in einen Abholordner kopiert. Ich möchte auch eine Kopie dieser Datei nehmen und sie in einem Archivordner mit dem Dateinamen ablegen

 yyyy-MM-dd.log

Was ist der einfachste Weg, dies in einem Windows-Stapeljob zu tun?

Ich suche im Grunde nach einem Äquivalent zu diesem Unix-Befehl:

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

Wenn Sie eine Datumszeichenfolge mit dem gewünschten Format in Windows .bat-Dateien abrufen, sieht dies genauso schlecht aus wie die vorgeschlagenen Lösungen. Ganz ehrlich, überprüfen Sie einfach, welche Programmiersprachen auf dem Computer verfügbar sind, z. B. Java, Ruby, Perl oder etwas anderes, und erstellen Sie eine ausführbare 5-Sekunden-Datei, um Ihnen das zu geben, was Sie möchten. Ich würde keine Zeit damit verschwenden, eine .bat-Datei zu verwalten, die mehr als eine Codezeile benötigt, um ein Datum mit einem geeigneten Format zu erhalten.
99 Sono

Antworten:


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

Aber es ist vom Gebietsschema abhängig. Ich bin nicht sicher, ob %DATE%es lokalisiert ist oder von dem Format abhängt, das für das kurze Datum in Windows angegeben wurde.

Hier ist eine vom Gebietsschema unabhängige Methode, um das aktuelle Datum aus dieser Antwort zu extrahieren. Dies hängt jedoch von WMICund ab 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
Musste ein bisschen mit den Indizes herumspielen, aber das scheint den Trick getan zu haben. (obwohl ich nicht ganz sicher bin, ob ich die Minus-Index-Logik verstehe)% DATE: ~ -4% -% DATE: ~ -7, -5% -% DATE: ~ -10, -8% .log
Eoin Campbell

1
Wenn Sie alle positiven Indizes verwenden
möchten, können Sie Folgendes

(Ich habe das gerade von etwas anderem genommen, an dem ich gearbeitet hatte, es ist lange her, und ich habe keine Ahnung, warum ich es so gemacht habe, wie ich es ursprünglich gemacht habe, heh.)
opello

3
Dies ist an anderen Orten nicht möglich. In meinem Fall kehrt der Befehl zurück 2014-5.-01(wenn es sein würde 2014-05-26). Seien Sie also sehr vorsichtig, wenn Sie Skripte veröffentlichen, die dies enthalten!
Amenthes

5
Verwenden Sie dies für die Zeit (entfernt Millisekunden): %time:~-11,2%-%time:~-8,2%-%time:~-5,2%
MRC

48

Dies funktionierte für mich und war eine dateinamensichere Lösung (obwohl sie ein MM-TT-JJJJ-Format generiert):

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

Der erste Befehl nimmt ein DATE und ersetzt /durch -, nimmt die TIME und ersetzt :durch -und kombiniert sie im DATE @ TIME-Format. Die zweite setAnweisung entfernt Leerzeichen und die dritte setersetzt die Erweiterung ,durch .und hängt sie an .jpg.

Der obige Code wird in einem kleinen Skript verwendet, das Bilder von einer IP-Sicherheitskamera zur weiteren Verarbeitung abruft:

: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

Die Ausgabe auf meiner Konsole erfolgt 10-12-2014@14-22-59,44.jpgmit einem Komma vor den Millisekunden
BeNdErR

1
Versuchen Sie, set SAVESTAMP=%SAVESTAMP:,=.%.jpgvor der echoAnweisung hinzuzufügen . Wenn das funktioniert, werde ich die Antwort aktualisieren.
Daniel Sokolowski

1
Dies ist nicht vom Gebietsschema unabhängig. Rückkehr 08.06.2016@15-42-20,33.jpgauf meinem deutschen und Wed06-08-2016@15-43-45.89.jpgmeinem englischen Laptop .
Hannobo

5
Aber es ist immer noch weder unabhängig vom Gebietsschema noch erstellt es das richtige (iso8601) Format vonyyyy-MM-dd
jeb

1
Es ist ärgerlich, dass die erste Zeile immer noch behauptet, es sei unabhängig vom Gebietsschema, nur um zu sehen, dass es nicht nach dem Ausprobieren ist ...
m3tikn0b

16

Seien Sie NUR für das französische Gebietsschema (Frankreich) vorsichtig, da es /im Datum angegeben ist:

echo %DATE%
08/09/2013

Für unser Problem mit der Protokolldatei ist hier NUR mein Vorschlag für das französische Gebietsschema :

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%

Ausgezeichnet! Ein wenig schwer zu lesen, aber es erlaubt, die Ausgabe so zu formatieren, wie Sie es möchten.
Davit vom

2
Großartig, aber seien Sie vorsichtig, wenn Sie weiße Zeichen vermeiden möchten, da HOUR eine Ziffer sein kann, die so gerendert wird: "_0:00"(das unterstrichene Zeichen ist ein Leerzeichen)
daVe

1
Ich bekomme "log- / 18 /. 0.Sa- 9.16.txt" für diese Antwort.
Ledlogic

@ledlogic: Was ist dein Gebietsschema? Diese Antwort gilt für das französische Gebietsschema.
Aubin

1
Funktioniert NICHT Ich bekomme das unter Windows 7 - log- / 05 /. 0.We-18.13.tx
Sam B

10

Hier ist eine vom Gebietsschema unabhängige Lösung (Kopie in eine Datei mit dem Namen 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%

Ich habe alle meine .cmd-Skripte in demselben Ordner abgelegt (% SCRIPTROOT%). Jedes Skript, das Datums- / Zeitwerte benötigt, ruft SetDateTimeComponents.cmd wie im folgenden Beispiel auf:

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%

Wie das Beispiel zeigt, können Sie SetDateTimeComponents.cmd jederzeit aufrufen, wenn Sie die Datums- / Zeitwerte aktualisieren müssen. Das Ausblenden des Zeitanalyse-Skripts in seiner eigenen SetDateTimeComponents.cmd-Datei ist eine gute Möglichkeit, die hässlichen Details auszublenden und vor allem Tippfehler zu vermeiden.


2
Entschuldigung, dies ist nicht unabhängig vom Gebietsschema: Unter meinem französischen Windows erhalte ich "18 -2014- @ 13:14:43"
Davit vom

1
Kann bestätigen: nicht länderunabhängig. prompt $d $tgibt 30.05.2016 15: 35: 56,93 auf meinem System zurück.
Hannobo

7

Da die Idee, sie auseinander zu reißen %DATE%und %TIME%auseinander zu zerdrücken, bestenfalls fragil erscheint, ist hier eine Alternative, die einen Powershell-Oneliner verwendet:

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

Referenz für get-dateist hier , mit Formatoptionen sowohl für .NET-Stil und UNIX-Stil.


6

Ich benutze dies häufig und füge alles in einen einzigen Kopierbefehl ein. Im Folgenden wird example.txt als example_YYYYMMDD_HHMMSS.txt kopiert, und Sie können es natürlich an Ihr bevorzugtes Format anpassen. Die Anführungszeichen sind nur erforderlich, wenn in der Dateispezifikation Leerzeichen vorhanden sind. Wenn Sie genau das gleiche Datum / den gleichen Zeitstempel wiederverwenden möchten, müssen Sie ihn in einer Variablen speichern.

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

Dadurch wird sichergestellt, dass die Ausgabe zweistellig ist. Sie können die Ausgabe nach Ihren Wünschen anordnen und testen, indem Sie den Kommentarbereich deaktivieren. Genießen!

(Ich habe viel davon aus anderen Foren ausgeliehen ...)

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

Erstellen Sie eine Datei mit dem aktuellen Datum als Dateiname (z. B. 2008-11-08.dat).

echo hello > %date%.dat    

Mit dem aktuellen Datum aber ohne das "-" (ex. 20081108.dat)

echo hello > %date:-=%.dat   

2

Vielleicht kann das helfen:

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

oder

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

Netter Secko ... dieser% date% Wert scheint das zu haben, wonach ich suche. Bei jeder Gelegenheit können Sie die SET-Anweisung erklären. Was genau sind $ d $ _set & $ t $ h $ h $ h
Eoin Campbell

1
set ist eine Anweisung "SET variable". Wobei die Datumsvariable $ d $ _ (Tag + der Rest) und die Zeitvariable $ t $ h $ h $ h (Zeit + ms) ist. Ich habe versucht zu zeigen, wie es mit einer Reihe von Variablen gemacht werden kann, es kann ohne die Eingabeaufforderungszeile gut funktionieren. Ich habe im Grunde versucht, dieses festgelegte Datum zu tun =% JJJJ %% MM %% TT%, aber ich verwende hier Linux und kompiliere das Skript auf SciTE, damit ich nicht weiß, ob es funktioniert. Entschuldigung, wenn es nicht funktioniert.
Secko

Ich habe vergessen hinzuzufügen, $ _ ist Newline.
Secko

1
Versuchen Sie auch, @prompt // $ d $ _ $ t $ h $ h $ h $ h $ h $ h //
Secko

Beachten Sie, dass dies auch nicht vom Gebietsschema unabhängig ist. Das Datum ist auf die aktuelle Kultureinstellung formatiert, in meinem Fall TT.MM.JJJJ (für Deutsch).
Hannobo

2

Ich habe ein kleines C-Programm zusammengestellt, um den aktuellen Zeitstempel auszudrucken (länderspezifisch, keine schlechten Zeichen ...). Dann benutze ich den Befehl FOR, um das Ergebnis in einer Umgebungsvariablen zu speichern:

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

Hier ist ein Link:

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


2

Ich weiß, dass dieser Thread alt ist, aber ich möchte ihn hier nur hinzufügen, weil er mir sehr geholfen hat, dies alles herauszufinden und es ist sauber. Das Schöne daran ist, dass Sie es in eine Schleife für eine Batch-Datei setzen können, die immer ausgeführt wird. Server-Betriebszeitprotokoll oder so. Dafür benutze ich es sowieso. Ich hoffe das hilft irgendwann jemandem.

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

Dies war nützlich für mich, obwohl in einer ".cmd" -Datei die Doppelpunkte in der "FreshTime" -Variable Fehler verursachten, wenn sie für einen Dateinamen in meiner "robocopy" -Cmdline verwendet wurden: ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"Als Fix habe ich stattdessen Bindestriche verwendet:set FreshTime=%hour%-%min%-%secs%
netdesignate

2

Sie können einfach das aktuelle lokale Format erkennen und das Datum in Ihrem Format abrufen, zum Beispiel:

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

Ich weiß, dass dies ein alter Beitrag ist, aber es gibt eine weitaus einfachere Antwort (obwohl dies möglicherweise nur in neueren Windows-Versionen funktioniert). Verwenden Sie einfach den Parameter / t für die Dos-Befehle DATE und TIME, um nur das Datum oder die Uhrzeit anzuzeigen und Sie nicht dazu aufzufordern, es wie folgt einzustellen:

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

1

1) Sie können GNU- Coreutils herunterladen, die mit dem GNU-Datum geliefert werden

2) Sie können VBScript verwenden , was die Datumsmanipulation in Windows erleichtert:

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

Führen Sie das Skript wie folgt aus:

c:\test> cscript /nologo myscript.vbs

0

Dies funktioniert gut mit (meinem) deutschen Gebietsschema, sollte es möglich sein, es an Ihre Bedürfnisse anzupassen ...

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%funktioniert auch für portugiesische Location! Ich meine JJJJMMTT
Fernando Fabreti

0

Für große Zip-Dateien für die Bereitstellung verwende ich Viertelstunden. Niemand sonst auf dieser Seite hatte es zuvor erwähnt, daher werde ich mein kleines Skript hier einfügen:

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"

Es ist noch keine Viertelstunde von Mitternacht bis 5 Uhr morgens, aber es macht es trotzdem so, dass Sie mehrmals am Tag eine gestempelte Veröffentlichung mit wenigen Kollisionen haben können.

Hoffentlich hilft das.


0

benutzte Martins Vorschlag mit einer kleinen Änderung, um dem Dateinamen einen Zeitstempel hinzuzufügen:

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

Für den 10:17:21 23/10/2019 Das Ergebnis ist:

20191023_10-17-21-rsync2.log

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.