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

90

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 colocarlo en una carpeta de archivo con el nombre de archivo

 yyyy-MM-dd.log

¿Cuál es la forma más sencilla 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
Eoin Campbell
fuente
Al obtener una cadena de fecha con el formato que desea en los archivos .bat de Windows, se ve tan mal como las soluciones propuestas. Honestamente, solo verifique qué lenguajes de programación están disponibles en la máquina, por ejemplo, java, ruby, perl o algo más, y haga un ejecutable de 5 segundos para obtener lo que desea. No perdería tiempo manteniendo un archivo .bat que requiere más de una línea de código para obtener una fecha con un formato adecuado.
99Sono

Respuestas:

105
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 la configuración regional para extraer la fecha actual de esta respuesta , pero depende de WMICy 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
fuente
6
Necesitaba jugar un poco con los índices, pero esto parece haber funcionado. (aunque no estoy completamente seguro de entender la lógica del índice negativo)% DATE: ~ -4% -% DATE: ~ -7, -5% -% DATE: ~ -10, -8% .log
Eoin Campbell
1
Si quisiera usar todos los índices positivos, podría usar:% DATE: ~ 10,4% -% DATE: ~ 4,2% -% DATE: ~ 7,2%
opello
(Acabo de tomar esto de otra cosa en la que había trabajado, fue hace mucho tiempo, y no tengo idea de por qué lo hice de la manera que lo hice originalmente, je)
opello
3
Esto se rompe en otras configuraciones regionales. En mi caso, el comando regresa 2014-5.-01(cuando sería 2014-05-26). ¡Así que tenga mucho cuidado si publica scripts que contengan esto!
Mejora
5
Use esto por el tiempo (elimina milisegundos): %time:~-11,2%-%time:~-8,2%-%time:~-5,2%
MRC
48

Esto funcionó para mí y fue 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%
[email protected]

El primer comando toma una FECHA y reemplaza /por -, toma la HORA y reemplaza :por -, y los combina en formato FECHA @ HORA. La segunda setdeclaración elimina cualquier espacio, y el tercero setsustituye ,con .y añade la .jpgextensión.

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:<password>@<ip address>:<port>/snapshot.cgi
timeout 1
GOTO while
Daniel Sokolowski
fuente
la salida en mi consola es 10-12-2014@14-22-59,44.jpgcon una coma antes de los milisegundos
BeNdErR
1
Intente agregar set SAVESTAMP=%SAVESTAMP:,=.%.jpgantes de la echodeclaración. Si eso funciona, actualizaré la respuesta.
Daniel Sokolowski
1
Esto no es independiente de la configuración regional. Devoluciones 08.06.2016@15-42-20,33.jpgen mi portátil alemán y [email protected]en mi inglés.
Hannobo
5
Pero todavía no es independiente de la configuración regional ni crea el formato correcto (iso8601) deyyyy-MM-dd
jeb
1
Es molesto que la primera línea todavía afirme que era independiente de la configuración regional, solo para ver que no lo es después de probar ...
m3tikn0b
16

SOLO para la configuración regional francesa (Francia) , tenga cuidado porque /aparece en la fecha:

echo %DATE%
08/09/2013

Para nuestro problema con el archivo de registro, aquí está mi propuesta SOLO para la configuración regional francesa :

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
fuente
¡Excelente! Un poco difícil de leer, pero permite formatear la salida como lo desea.
pescante del
2
Genial, pero tenga cuidado si desea evitar los caracteres blancos porque la HORA puede ser de 1 dígito representado así: "_0:00"(el carácter subrayado es un espacio)
daVe
1
Obtengo "log- / 18 /. 0.Sa- 9.16.txt" para esta respuesta.
ledlogic
@ledlogic: ¿cuál es tu localidad? Esta respuesta es para la configuración regional francesa.
Aubin
1
NO funciona Recibo esto en Windows 7 - log- / 05 /. 0.We-18.13.tx
Sam B
10

Aquí hay una solución independiente de la configuración regional (cópiela 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%

Pongo 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 siempre 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 forma de ocultar los detalles desagradables y, lo que es más importante, evitar errores tipográficos.

totorocat
fuente
2
lo siento, esto no es independiente de la configuración regional: en mi Windows francés, obtengo "18-2014- @ 13:14:43"
davitof
1
Puede confirmar: no independiente de la configuración regional. prompt $d $tdevuelve 30.05.2016 15: 35: 56,93 en mi sistema.
Hannobo
7

Debido a que la idea de desgarrarlos %DATE%y %TIME%volverlos a mezclar parece frágil en el mejor de los casos, aquí hay una alternativa que usa 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 de get-dateestá aquí , con opciones de formato tanto para el estilo .NET como para el estilo UNIX.

tboz203
fuente
6

Utilizo esto con frecuencia y pongo todo en un solo comando de copia. La siguiente copia example.txt como example_YYYYMMDD_HHMMSS.txt y, por supuesto, puede modificarlo para adaptarlo a su formato preferido. Las comillas solo son necesarias si hay espacios en la especificación de archivo. Si desea reutilizar exactamente la misma fecha / marca de tiempo, 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"
Sé conciso
fuente
6

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

(Tomé prestado mucho de esto de 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%
Rick Rubino
fuente
2

Cree un archivo con la fecha actual como nombre de archivo (por ejemplo, 2008-11-08.dat)

echo hello > %date%.dat    

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

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

Quizás esto pueda 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%
Secko
fuente
Bonito Secko ... ese valor de% date% parece tener lo que estoy buscando. En cualquier oportunidad, puede explicar la declaración SET. ¿Qué son exactamente $ d $ _set & $ t $ h $ h $ h
Eoin Campbell
1
set es una declaración "SET variable". Donde la variable de fecha es $ d $ _ (día + el resto) y la variable de tiempo es $ t $ h $ h $ h (tiempo + ms). Traté de mostrar cómo se puede hacer con un conjunto de variables, puede funcionar bien sin la línea de solicitud. Básicamente intenté hacer esta fecha establecida =% YYYY %% MM %% DD% pero estoy ejecutando Linux aquí y compilando el script en SciTE, así que no sé si funciona. Lo siento si no funciona.
Secko
Olvidé agregar, $ _ es nueva línea.
Secko
1
Prueba también, @prompt // $ d $ _ $ t $ h $ h $ h $ h $ h $ h //
Secko
Tenga en cuenta que esto tampoco es independiente de la configuración regional. La fecha tiene el formato de la configuración cultural actual, en mi caso DD.MM.YYYY (para alemán).
Hannobo
2

Reuní un pequeño programa en C para imprimir la marca de tiempo actual (seguro para la configuración regional, sin caracteres malos ...) Luego, uso 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

Harry Pehkonen
fuente
2

Sé que este hilo es antiguo, pero solo quiero agregar esto aquí porque me ayudó mucho a tratar de resolver todo esto y está limpio. Lo bueno de esto es que podría ponerlo en un bucle para un archivo por lotes que siempre se está ejecutando. Registro de tiempo de actividad del servidor o algo así. Para eso lo uso de 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%
Haxslie
fuente
Esto fue útil para mí, aunque en un archivo ".cmd", los dos puntos en la variable "FreshTime" causaban errores cuando se usaban para un nombre de archivo en mi línea de cmd "robocopy": ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"como solución, usé guiones en su lugar:set FreshTime=%hour%-%min%-%secs%
netdesignate
2

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
Adam Silenko
fuente
2

Sé que esta es una publicación antigua, pero hay una respuesta MUCHO más simple (aunque tal vez solo funcione 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 le pida que la configure, así:

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

1) Puede descargar GNU coreutils que viene con la fecha GNU

2) puede usar VBScript , lo que facilita la manipulación de fechas 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
ghostdog74
fuente
0

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"
Martín
fuente
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%¡Funciona para la ubicación portuguesa también! Me refiero a AAAAMMDD
Fernando Fabreti
0

Para archivos zip grandes para la implementación, utilizo un cuarto de hora. Nadie más en esta página lo había mencionado antes, así que pondré mi pequeño guión aquí:

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"

Todavía no pone a cero los cuartos de hora desde la medianoche hasta las 5 a.m., pero aún lo hace para que pueda tener una liberación sellada varias veces al día con pocas colisiones.

Espero que ayude.

phyatt
fuente
0

usó la sugerencia de Martin con un pequeño ajuste para agregar una marca de tiempo al nombre del archivo:

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

Para las 10:17:21 23/10/2019 El resultado es:

20191023_10-17-21-rsync2.log

Gennady Sorochan
fuente