Crear un nombre de archivo como una marca de tiempo en un trabajo por lotes

Tenemos un trabajo por lotes que se ejecuta todos los días y copia un archivo en una carpeta de recogida. También quiero tomar una copia de ese archivo y soltarlo en una carpeta de archivo con el nombre del archivo

yyyy-MM-dd.log 

¿Cuál es la forma más fácil de hacer esto en un trabajo por lotes de Windows?

Básicamente estoy buscando un equivalente de este comando de Unix:

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

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

Pero depende de la configuración regional. No estoy seguro de si %DATE% está localizado, o depende del formato especificado para la fecha corta en Windows.

Aquí hay una forma independiente de configuración regional para extraer la fecha actual de esta respuesta , pero depende de WMIC y 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 

Esto funcionó para mí y era una solución segura para el nombre de archivo (aunque genera un formato MM-dd-YYYY):

 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 

El primer comando toma una FECHA y reemplaza / con - , toma el TIEMPO y reemplaza : con - , y los combina con el formato FECHA @ HORA. La segunda statement de set elimina cualquier espacio, y el tercer set reemplaza , con . y agrega la extensión .jpg .

El código anterior se utiliza en un pequeño script que extrae imágenes de una cámara IP de seguridad para su posterior procesamiento:

 :while set SAVESTAMP=%DATE:/=-%@%TIME::=-% set SAVESTAMP=%SAVESTAMP: =% set SAVESTAMP=%SAVESTAMP:,=.%.jpg wget-1.10.2.exe --tries=0 -O %SAVESTAMP% http://admin:@:/snapshot.cgi timeout 1 GOTO while 

Para la configuración regional francesa (Francia) ÚNICAMENTE , tenga cuidado porque / aparece en la fecha:

 echo %DATE% 08/09/2013 

Para nuestro problema de archivo de registro, esta es mi propuesta SOLAMENTE para la configuración regional en francés :

 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% 

Aquí hay una solución independiente de configuración regional (copie en un archivo llamado 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% 

Puse todos mis scripts .cmd en la misma carpeta (% SCRIPTROOT%); cualquier script que necesite valores de fecha / hora llamará a SetDateTimeComponents.cmd como en el siguiente ejemplo:

 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% 

Como muestra el ejemplo, puede llamar a SetDateTimeComponents.cmd cada vez que necesite actualizar los valores de fecha / hora. Ocultar el script de análisis de tiempo en su propio archivo SetDateTimeComponents.cmd es una buena manera de ocultar los detalles desagradables y, lo que es más importante, evitar los errores tipográficos.

Esto asegurará que la salida sea un valor de 2 dígitos … puede reorganizar la salida a su gusto y probar desactivándola de la sección de diagnóstico. ¡Disfrutar!

(Pedí mucho de esto en otros foros …)

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

Con frecuencia uso esto y pongo todo en un solo comando de copia. La siguiente copia example.txt como example_YYYYMMDD_HHMMSS.txt y, por supuesto, puede modificarla para adaptarla a su formato preferido. Las comillas solo son necesarias si hay espacios en la especificación de archivos. Si desea reutilizar la misma fecha / marca de tiempo exacta, deberá almacenarla en una 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" 

Crea un archivo con la fecha actual como nombre de archivo (ej. 2008-11-08.dat)

 echo hello > %date%.dat 

Con la fecha actual pero sin el “-” (ej. 20081108.dat)

 echo hello > %date:-=%.dat 

Tal vez esto puede ayudar:

 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% 

Arreglé un pequeño progtwig en C para imprimir la marca de tiempo actual (seguro para la configuración regional, sin malos caracteres …). Luego, utilizo el comando FOR para guardar el resultado en una variable de entorno:

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

Aquí hay un enlace:

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

Simplemente puede detectar el formato local actual y puede obtener la fecha en su formato, por ejemplo:

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

Sé que esta es una publicación anterior, pero hay una respuesta mucho más simple (aunque tal vez solo funciona en versiones más nuevas de Windows). Simplemente use el parámetro / t para los comandos DATE y TIME dos para mostrar solo la fecha o la hora y no solicitarle que lo configure, como este:

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

Debido a que la idea de dividir %DATE% y %TIME% y mezclarlos nuevamente parece frágil en el mejor de los casos, he aquí una alternativa que utiliza un delineador 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 referencia para get-date está aquí , con opciones de formato para .NET-style y UNIX-style.

1) Puedes descargar GNU coreutils que viene con fecha de GNU

2) puede usar VBScript , lo que facilita la manipulación de la fecha en 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 

Ejecute el script como:

 c:\test> cscript /nologo myscript.vbs 

Sé que este hilo es viejo, pero solo quiero agregar esto aquí porque me ayudó mucho tratando de resolver todo esto y está limpio. Lo bueno de esto es que podrías ponerlo en un bucle para un archivo por lotes que siempre se está ejecutando. Registro de tiempo de actividad del servidor o algo así. De eso es lo que lo uso para todos modos. Espero que esto ayude a alguien algún día.

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

Esto funciona bien con (mi) configuración regional alemana, debería ser posible ajustarlo a sus necesidades …

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