Criar um nome de arquivo como um carimbo de data / hora em um trabalho em lote

90

Temos um trabalho em lote que é executado todos os dias e copia um arquivo para uma pasta de coleta. Também quero fazer uma cópia desse arquivo e colocá-lo em uma pasta de arquivo com o nome do arquivo

 yyyy-MM-dd.log

Qual é a maneira mais fácil de fazer isso em um trabalho em lote do Windows?

Basicamente, estou procurando um equivalente a este comando Unix:

cp source.log `date +%F`.log
Eoin Campbell
fonte
Ao obter uma string de data com o formato desejado nos arquivos .bat do windows parece tão ruim quanto as soluções propostas. Sinceramente, apenas verifique quais linguagens de programação estão disponíveis na máquina, por exemplo, java, ruby, perl ou outra coisa, e faça um executável de 5 segundos para fornecer o que você deseja. Eu não perderia tempo mantendo um arquivo .bat que requer mais de uma linha de código para obter uma data com um formato adequado.
99Sono

Respostas:

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

Mas é dependente da localidade. Não tenho certeza se %DATE%está localizado ou depende do formato especificado para a data abreviada no Windows.

Esta é uma maneira independente de localidade para extrair a data atual desta resposta , mas depende de 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
opello
fonte
6
Precisava mexer um pouco nos índices, mas isso parece ter funcionado. (embora não tenha certeza se entendo a lógica do índice negativo)% DATA: ~ -4% -% DATA: ~ -7, -5% -% DATA: ~ -10, -8% .log
Eoin Campbell
1
Se você quiser usar todos os índices positivos, pode usar:% DATA: ~ 10,4% -% DATA: ~ 4,2% -% DATA: ~ 7,2%
opello
(Acabei de tirar isso de outra coisa em que trabalhei, foi há muito tempo, e não tenho ideia de por que fiz do jeito que fiz originalmente, heh.)
opello
3
Isso não funciona em outros locais. No meu caso o comando retorna 2014-5.-01(quando seria 2014-05-26). Portanto, tenha muito cuidado ao publicar scripts que contenham isso!
amenthes
5
Use isto para o tempo (remove milissegundos): %time:~-11,2%-%time:~-8,2%-%time:~-5,2%
MRC
48

Isso funcionou para mim e era uma solução segura para nomes de arquivos (embora gere um formato MM-dd-AAAA):

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

O primeiro comando pega uma DATA e substitui /com -, pega a HORA e substitui :com -, e os combina no formato DATA @ HORA. A segunda setdeclaração remove quaisquer espaços, eo terceiro setsubstitui ,com .e acrescenta o .jpgextensão.

O código acima é usado em um pequeno script que extrai imagens de uma câmera IP de segurança para processamento posterior:

: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
fonte
a saída em meu console está 10-12-2014@14-22-59,44.jpgcom uma vírgula antes dos milissegundos
BeNdErR
1
Experimente adicionar set SAVESTAMP=%SAVESTAMP:,=.%.jpgantes da echodeclaração. Se funcionar, atualizarei a resposta.
Daniel Sokolowski
1
Isso não é independente do local. Retorna 08.06.2016@15-42-20,33.jpgno meu laptop alemão e [email protected]no meu inglês.
Hannobo
5
Mas ainda não é nem locale independet nem ele cria o formato correto (ISO8601) deyyyy-MM-dd
jeb
1
É irritante que a primeira linha ainda alega que era independente do local, só para ver que não é depois de tentar ...
m3tikn0b
16

SOMENTE para a localidade francesa (França) , tome cuidado porque /aparece na data:

echo %DATE%
08/09/2013

Para o nosso problema de arquivo de log, aqui está minha proposta APENAS para a localidade 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
fonte
Excelente! Um pouco difícil de ler, mas permite formatar a saída como você deseja.
Davitof de
2
Ótimo, mas tenha cuidado se você quiser evitar caracteres brancos porque HOUR pode ser 1 dígito renderizado assim: "_0:00"(o caractere sublinhado é um espaço)
dia
1
Recebo "log- / 18 /. 0.Sa- 9.16.txt" para esta resposta.
ledlogic
@ledlogic: qual é a sua localidade? Esta resposta é para o idioma francês.
Aubin
1
NÃO funciona Recebo isso no Windows 7 - log- / 05 /. 0.We-18.13.tx
Sam B
10

Esta é uma solução independente de localidade (copie para um arquivo denominado 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%

Coloquei todos os meus scripts .cmd na mesma pasta (% SCRIPTROOT%); qualquer script que precise de valores de data / hora chamará SetDateTimeComponents.cmd como no exemplo a seguir:

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 mostra o exemplo, você pode chamar SetDateTimeComponents.cmd sempre que precisar atualizar os valores de data / hora. Ocultar o script de análise de tempo em seu próprio arquivo SetDateTimeComponents.cmd é uma boa maneira de ocultar os detalhes feios e, mais importante, evitar erros de digitação.

totorocat
fonte
2
desculpe, isso não é independente da localidade: no meu Windows francês, recebo "18 -2014- @ 13:14:43"
davitof
1
Pode confirmar: não independente do local. prompt $d $tretorna 30/05/2016 15: 35: 56,93 no meu sistema.
Hannobo
7

Porque a idéia de rasgar %DATE%e %TIME%distante e esmagou-los juntos novamente parece frágil na melhor das hipóteses, aqui está uma alternativa que utiliza um powershell oneliner:

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

A referência para get-dateestá aqui , com opções de formato para os estilos .NET e UNIX.

tboz203
fonte
6

Eu freqüentemente uso isso e coloco tudo em um único comando de cópia. O seguinte copia example.txt como example_YYYYMMDD_HHMMSS.txt e, claro, você pode modificá-lo para se adequar ao seu formato preferido. As aspas são necessárias apenas se houver espaços na especificação do arquivo. Se você quiser reutilizar exatamente a mesma data / carimbo de data / hora, precisará armazená-lo em uma variável.

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

Isso garantirá que a saída seja um valor de 2 dígitos ... você pode reorganizar a saída de acordo com sua preferência e testar removendo os comentários da seção de diagnóstico. Aproveitar!

(Eu peguei emprestado muito disso de outros fóruns ...)

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

Crie um arquivo com a data atual como nome de arquivo (ex. 2008-11-08.dat)

echo hello > %date%.dat    

Com a data atual, mas sem o "-" (ex. 20081108.dat)

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

Talvez isso possa ajudar:

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
fonte
Boa, Secko ... esse valor de% date% parece ter o que estou procurando. Qualquer chance de você pode explicar a instrução SET. O que exatamente são $ d $ _set & $ t $ h $ h $ h
Eoin Campbell
1
set é uma instrução "SET variável". Onde a variável de data é $ d $ _ (dia + o resto) e a variável de tempo é $ t $ h $ h $ h (tempo + ms). Tentei mostrar como isso pode ser feito com um conjunto de variáveis, pode funcionar bem sem a linha de prompt. Basicamente tentei fazer isso set date =% YYYY %% MM %% DD%, mas estou rodando Linux aqui e compilando o script no SciTE, então não sei se funciona. Desculpe se não funcionar.
Secko
Esqueci de adicionar, $ _ é nova linha.
Secko
1
Tente também, @prompt // $ d $ _ $ t $ h $ h $ h $ h $ h $ h //
Secko
Observe que isso também não é independente da localidade. A data é formatada para a configuração de cultura atual, no meu caso DD.MM.AAAA (para alemão).
Hannobo
2

Eu montei um pequeno programa C para imprimir o carimbo de data / hora atual (locale-seguro, sem caracteres inválidos ...). Então, eu uso o comando FOR para salvar o resultado em uma variável de 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"

Aqui está um link:

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

Harry Pehkonen
fonte
2

Eu sei que este tópico é antigo, mas eu só quero adicionar isso aqui porque me ajudou muito tentando descobrir tudo isso e está limpo. O bom disso é que você pode colocá-lo em um loop para um arquivo em lote que está sempre em execução. Log de tempo de atividade do servidor ou algo assim. É para isso que eu uso de qualquer maneira. Espero que isso ajude alguém algum dia.

@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
fonte
Isso foi útil para mim, embora em um arquivo ".cmd", os dois pontos na variável "FreshTime" causassem erros quando usados ​​para um nome de arquivo em meu cmdline "robocopy": ERROR : Invalid Parameter #12 : "/LOG:C:\opt\Sync_08.10.2020_16:27:39.log"Como uma correção, usei traços em vez disso:set FreshTime=%hour%-%min%-%secs%
netdesignate
2

Você pode simplesmente detectar o formato local atual e obter a data em seu formato, por exemplo:

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

Eu sei que este é um post antigo, mas há uma resposta MUITO mais simples (embora talvez só funcione em versões mais recentes do Windows). Basta usar o parâmetro / t para os comandos DATE e TIME dos para mostrar apenas a data ou hora e não solicitar que você as defina, como este:

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

1) Você pode baixar GNU coreutils que vem com a data GNU

2) você pode usar o VBScript , o que torna a manipulação de datas mais fácil no 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

Execute o script como:

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

Isso funciona bem com (meu) idioma alemão, deve ser possível ajustá-lo às suas necessidades ...

forfiles /p *PATH* /m *filepattern* /c "cmd /c ren @file 
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%_@file"
Martin
fonte
%DATE:~6,4%%DATE:~3,2%%DATE:~0,2%funciona para a localização portuguesa também! Quero dizer AAAAMMDD
Fernando Fabreti
0

Para grandes arquivos zip para implantação, eu uso um quarto de hora. Ninguém mais nesta página mencionou isso antes, então vou colocar meu pequeno script aqui:

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"

Ele não zera um quarto de hora da meia-noite às 5 da manhã ainda, mas ainda permite que você tenha uma versão carimbada várias vezes ao dia com poucas colisões.

Espero que ajude.

Phyatt
fonte
0

usou a sugestão de Martin com um pequeno ajuste para adicionar carimbo de data / hora ao nome do arquivo:

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 10:17:21 23/10/2019 O resultado é:

20191023_10-17-21-rsync2.log

Gennady Sorochan
fonte