Data e hora do comando em lote no nome do arquivo

Estou compactando arquivos usando o WinZip na linha de comando. Como arquivamos diariamente, estou tentando adicionar data e hora a esses arquivos para que um novo seja gerado automaticamente todas as vezes.

Eu uso o seguinte para gerar um nome de arquivo. Copie e cole na sua linha de comando e você verá um nome de arquivo com um componente Data e hora.

echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2%%time:~6,2%.zip 

Saída

 Archive_20111011_ 93609.zip 

No entanto, meu problema é AM vs. PM . O carimbo de hora AM dá-me o tempo 9 (com um espaço em branco à esquerda) vs. 10 ocupando naturalmente os dois espaços.

Eu acho que meu problema vai se estender até os primeiros nove dias, primeiros 9 meses, etc. também.

Como corrijo isso para que zeros à esquerda sejam incluídos em vez de espaços em branco iniciais, por isso recebo Archive_20111011_093609.zip ?

Outra solução

 for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /format:list') do set datetime=%%I 

Isso lhe dará (independente das configurações de localidade!):

  20130802203023.304000+120 ( YYYYMMDDhhmmss.+/- ) 

A partir daqui, é fácil:

 set datetime=%datetime:~0,8%-%datetime:~8,6% 20130802-203023 

Para a solicitação do Logan para o mesmo formato de saída para o “data-hora modificada” de um arquivo:

 for %%F in (test.txt) do set file=%%~fF for /f "tokens=2 delims==" %%I in ('wmic datafile where name^="%file:\=\\%" get lastmodified /format:list') do set datetime=%%I echo %datetime% 

É um pouco mais complicado, porque funciona apenas com caminhos completos, o wmic espera que as barras invertidas sejam duplicadas e o = deve ser escapado (o primeiro. O segundo é protegido por cotações circunvizinhas).

Extraia a hora, procure por um espaço à esquerda, se for encontrado, substitua por um zero;

 set hr=%time:~0,2% if "%hr:~0,1%" equ " " set hr=0%hr:~1,1% echo Archive_%date:~-4,4%%date:~-10,2%%date:~-7,2%_%hr%%time:~3,2%%time:~6,2%.zip 

Você deveria procurar; você pode simplesmente replace todos os espaços com zero set hr=%hr: =0%jeb Out 11 ’11 at 14:16

Então eu fiz:

 set hr=%time:~0,2% set hr=%hr: =0% 

Em seguida, use %hr% dentro de qualquer string que você esteja formatando para obter sempre uma hora de dois dígitos.

(O comentário de Jeb sob a resposta mais popular funcionou melhor para mim e é o mais simples. Eu repostá-lo aqui para torná-lo mais óbvio para futuros usuários.)

Como Vicky já apontou, %DATE% e %TIME% retornam a data e hora atuais usando os formatos curtos de data e hora que são totalmente (infinitamente) personalizáveis.

Um usuário pode configurar seu sistema para retornar Fri040811 08.03PM enquanto outro usuário pode escolher 08/04/2011 20:30.

É um pesadelo completo para um programador BAT.

Alterar o formato para um formato firme pode corrigir o problema, desde que você restaure o formato anterior antes de sair do arquivo BAT. Mas pode estar sujeito a condições desagradáveis ​​de corrida e complicar a recuperação de arquivos BAT cancelados.

Felizmente, existe uma alternativa.

Você pode usar o WMIC. WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table retorna a data e hora de maneira invariável. Muito conveniente para analisá-lo diretamente com um comando FOR /F

Então, juntando as peças, tente isso como um ponto de partida …

 SETLOCAL enabledelayedexpansion FOR /F "skip=1 tokens=1-6" %%A IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO ( SET /A FD=%%F*1000000+%%D*100+%%A SET /A FT=10000+%%B*100+%%C SET FT=!FT:~-4! ECHO Archive_!FD!_!FT!.zip ) 

Eu encontrei a melhor solução para mim, depois de ler todas as suas respostas:

 set t=%date%_%time% set d=%t:~10,4%%t:~7,2%%t:~4,2%_%t:~15,2%%t:~18,2%%t:~21,2% echo hello>"Archive_%d%" 

Se eu recebo 20160915_ 150101 (com espaço e tempo 20160915_ 150101 ).

Se PM eu recebo 20160915_2150101 .

Você pode adicionar zeros à esquerda a uma variável (valor até 99) como este no lote: IF 1%Var% LSS 100 SET Var=0%Var%

Então, você precisaria analisar seus componentes de data e hora em variables ​​separadas, tratá-los todos dessa maneira e, em seguida, concatená-los novamente para criar o nome do arquivo.

No entanto, o método subjacente para data e hora de análise depende das configurações de localidade do sistema. Se você está feliz por seu código não ser portável para outras máquinas, provavelmente está tudo bem, mas se você espera que ele funcione em diferentes contextos internacionais, então você precisará de uma abordagem diferente, por exemplo, lendo as configurações do registro:

 HKEY_CURRENT_USER\Control Panel\International\iDate HKEY_CURRENT_USER\Control Panel\International\iTime HKEY_CURRENT_USER\Control Panel\International\iTLZero 

(Esse último controla se há um zero à frente, mas não datas até onde eu sei).

 @For /F "tokens=1,2,3,4 delims=/ " %%A in ('Date /t') do @( Set DayW=%%A Set Day=%%B Set Month=%%C Set Year=%%D Set All=%%D%%B%%C ) "C:\Windows\CWBZIP.EXE" "c:\transfer\ziptest%All%.zip" "C:\transfer\MB5L.txt" 

Isso leva MB5L.txt e comprime-lo para ziptest20120204.zip se executado em 4 de fevereiro de 2012

Sua pergunta parece estar resolvida, mas …

Não tenho certeza se você pegar a solução certa para o seu problema.
Eu suponho que você tente compactar cada dia o código do projeto real.

É possível com ZIP e 1980 esta foi uma boa solução, mas hoje você deve usar um sistema de repository, como subversion ou git ou …, mas não um arquivo zip.

Ok, talvez possa ser que eu esteja errado.

A partir da resposta acima, eu fiz uma function pronta para uso.

Validado com configurações locais francesas.

 :::::::: PROGRAM :::::::::: call:genname "my file 1.txt" echo "%newname%" call:genname "my file 2.doc" echo "%newname%" echo.&pause&goto:eof :::::::: FUNCTIONS ::::::::: :genname set d1=%date:~-4,4% set d2=%date:~-10,2% set d3=%date:~-7,2% set t1=%time:~0,2% ::if "%t1:~0,1%" equ " " set t1=0%t1:~1,1% set t1=%t1: =0% set t2=%time:~3,2% set t3=%time:~6,2% set filename=%~1 set newname=%d1%%d2%%d3%_%t1%%t2%%t3%-%filename% goto:eof 

Eu percebo que esta é uma questão controversa para o OP, mas eu acabei de fazer isso, e estou um pouco orgulhoso de mim mesmo por pensar fora da checkbox.

Faça o download do gawk para Windows em http://gnuwin32.sourceforge.net/packages/gawk.htm …. Então é um liner, sem toda aquela syntax desajeitada do DOS, onde são necessários seis loops FOR para dividir as strings (WTF “Isso é realmente muito mal MAD e triste! … IMHO, claro)

Se você já conhece C, C ++, Perl ou Ruby, então pegar AWK (que herda dos dois primeiros e contribui significativamente para os dois últimos) é uma parte do proverbial bolo !!!

O comando DOS Batch:

 echo %DATE% %TIME% && echo %DATE% %TIME% | gawk -F"[ /:.]" "{printf(""""%s%02d%02d-%02d%02d%02d\n"""", $4, $3, $2, $5, $6, $7);}" 

Impressões:

 Tue 04/09/2012 10:40:38.25 20120904-104038 

Agora essa não é a história completa … Eu só vou ser preguiçoso e codificar o resto do meu nome de arquivo de log na declaração printf, porque é simples … Mas se alguém sabe como definir um % NOW% variável para a saída do AWK (sem perder a coragem de uma function “genérica” ​​agora), então eu sou todo ouvidos.


EDITAR:

Uma pesquisa rápida no Stack Overflow preencheu a última peça do quebra-cabeça, o equivalente em lote dos backshks do Bash .

Então, essas três linhas de lote do DOS:

 echo %DATE% %TIME% | awk -F"[ /:.]" "{printf(""""%s%02d%02d-%02d%02d%02d\n"""", $4, $3, $2, $5, $6, $7);}" >%temp%\now.txt set /p now=< %temp%\now.txt echo %now% 

Produzir:

 20120904-114434 

Então agora eu posso include um datetime no nome do arquivo de log produzido pelo meu script de instalação do SQL Server (2005+) assim:

 sqlcmd -S .\SQLEXPRESS -d MyDb -e -i MyTSqlCommands.sql >MyTSqlCommands.sql.%now%.log 

E eu sou um campista feliz novamente (exceto que a vida ainda era SOOOOO muito mais fácil no Unix).

Um espaço é legal em nomes de arquivos. Se você colocar seu caminho e nome de arquivo entre aspas, ele pode simplesmente voar. Aqui está o que estou usando em um arquivo em lotes:

 svnadmin hotcopy "C:\SourcePath\Folder" "f:\DestPath\Folder%filename%" 

Não importa se há espaços em% filename%.