文件名中的批处理命令日期和时间


72

我在命令行上使用WinZip压缩文件。由于我们每天存档,因此我尝试为这些文件添加日期和时间,以便每次自动生成一个新文件。

我使用以下命令生成文件名。复制将其粘贴到您的命令行中,您应该看到带有日期和时间组件的文件名。

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

输出量

Archive_20111011_ 93609.zip

但是,我的问题是AM vs PM。AM时间戳给了我时间9(前导空格),而不是10自然地占用了两个空格。

我想我的问题还将延伸到前九天,前9个月等。

我如何解决此问题,以便包括前导零而不是前导空格,这样我就能得到Archive_20111011_093609.zip


3
我最终将您的任务用于日常任务,所有答案都更加混乱。
rrrhys 2015年

Answers:


75

另一个解决方案:

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

它会给您(与语言环境设置无关!):

  20130802203023.304000+120
( YYYYMMDDhhmmss.<milliseconds><always 000>+/-<minutes difference to UTC>  )

从这里开始,很容易:

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

对于Logan对于文件的“修改日期时间”的相同输出格式的请求:

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%

这有点复杂,因为它仅适用于完整路径,wmic期望反斜杠加倍并且=必须转义(第一个反斜杠。第二个反斜杠由周围的引号保护)。


1
辉煌!(wmic命令的示例输出:LocalDateTime=20140619212037.828000+120
Peter Mortensen 2014年

不为我工作%%I was unexpected at this time
Trikaldarshiii 2014年

3
@AnonymousMohit:%%I用于批处理文件。如果直接在命令提示符下使用该行,则必须改为使用%I
Stephan

@Stephan您知道如何执行此操作以类似的格式获取文件的“修改日期”吗?
Logan 2015年

@Logan:直到现在我都没有,但是我找到了解决方案。看到我的编辑。
斯蒂芬

60

提取小时,寻找前导空格,如果找到则替换为零;

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

11
为什么要搜索,您可以将所有空格简单地替换为零set hr=%hr: =0%
jeb 2011

3
@jeb,为什么要评论而不回答?
JoelFan 2012年

我得到了Archive_b-%a%cc-_142053.zip
AsyncMoksha 2014年

3
@ZinanXing:因为此解决方案取决于本地设置(不同国家的日期/时间字符串的格式不同)。这就是为什么我更喜欢wmic解决方案(请参阅我对这个问题的回答)
Stephan

22

您应该搜索;您可以简单地将所有空格替换为零set hr=%hr: =0%jeb 2011 年11月11日14:16

所以我做了:

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

然后%hr%在要格式化的任何字符串中使用以始终获得两位数的小时数。

(Jeb在最受欢迎的答案下的评论对我来说是最有效的,也是最简单的。我将其重新张贴在此处,以使其对将来的用户更加明显。)


2
遗憾的是您无法链接转换。%time:~0,2: =0%本来不错。:^(
Michael

在我看来,这是最好的解决方案。我向发送WMIC信息的人们表示祝贺。主要是独立日期格式“ wmic os get localdatetime”对我来说非常有用。保持良好...
ZEE

哇,真的很酷,解决方法也很短。我不知道您可以在环境变量中替换数字:D
Radon8472 '18

17

正如Vicky所指出的,%DATE%%TIME%使用完全(无限)可定制的短日期和时间格式返回当前日期和时间。

一个用户可以配置其系统以返回Fri040811 08.03PM,而另一用户可以选择08/04/2011 20:30。

对于BAT程序员来说,这是一场噩梦。

将格式更改为固定格式可能会解决此问题,前提是您在退出BAT文件之前恢复了以前的格式。但是它可能会受到讨厌的比赛条件的影响,并且在已取消的BAT文件中恢复过程会变得很复杂。

幸运的是,还有另一种选择。

您可以改为使用WMIC。WMIC Path Win32_LocalTime Get Day,Hour,Minute,Month,Second,Year /Format:table以不变的方式返回日期和时间。使用FOR /F命令直接解析非常方便。

因此,将各个部分放在一起,以此作为起点...

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
 )

16

阅读所有答案后,我找到了最适合我的解决方案:

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

如果是上午,我会得到20160915_ 150101(时空领先)。

如果下午我得到20160915_2150101


如果添加,set d=%d: =0%它将用零替换该空间。
CrazyPenguin

1
谢谢CrazyPenguin set t =%date%_%time%set d =%t:〜10,4 %% t:〜7.2 %% t:〜4.2 %% _ t:〜15,2 %% t :〜18,2 %% t:〜21,2%设置d =%d:= 0%echo hello>“ Archive_%d%”
Nesar

如果有人想知道“ set d =%d:= 0%”的位置,它将在第2行和第3行之间
Nesar

4

您可以像这样批量添加前导零到变量(值最大为99): IF 1%Var% LSS 100 SET Var=0%Var%

因此,您需要将日期和时间成分解析为单独的变量,将其全部处理,然后将它们重新连接在一起以创建文件名。

但是,用于解析日期和时间的基础方法取决于系统区域设置。如果您很高兴自己的代码不能移植到其他计算机上,那可能很好,但是如果您希望它可以在不同的国际环境中工作,那么您将需要一种不同的方法,例如通过读取注册表设置:

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

(最后一个控制时间是否存在前导零,但据我所知没有日期)。


我想再给您+1的语言环境设置。我正在公司的服务器上执行此操作,因此在这些服务器上不能更改区域设置,因此我相当安全。日期和时间纯粹是作业运行时间的指示。
Raj More

4
@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"

如果运行于2012年2月4日,则它将使用MB5L.txt并将其压缩为ziptest20120204.zip


2

根据上面的答案,我已经准备好使用的功能。

经过法国本地设置验证。

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

1

您的问题似乎已解决,但是...

我不确定您是否针对您的问题采用了正确的解决方案。
我想您尝试每天压缩实际的项目代码。

ZIP和1980可能是个不错的解决方案,但是今天您应该使用存储库系统,例如subversion或git或...,但不要使用zip文件。

好的,也许是我错了。


2
您刚刚以1980年的评论为自己和老朋友约会。现在再读一次我的问题,您会发现我再也没有提到我正在压缩任何代码。为了清楚起见,我正在存档ETL流程中使用的传入文件。
Raj More

1
是的,您从未提到要压缩的内容,这就是为什么我只猜到了。由于编码人员经常使用SO,因此我猜错了可能是代码。是的,我是个老计时器(但这只是一个观点)
jeb 2011年

1

正如其他人已经指出的那样,%DATE%and %TIME%(以及date /Tand time /T)的日期和时间格式取决于语言环境,因此提取当前日期和时间始终是一场噩梦,并且不可能获得一种适用于所有可能情况的解决方案。格式,因为几乎没有格式限制。


但存在与像以下之一的代码的另一个问题(让我们假定日期格式像MM/DD/YYYY和像一个12小时时间格式h:mm:ss.ff ap,其中ap或者是AMPMff是秒的小数部分):

rem // Resolve AM/PM time:
set "HOUR=%TIME:~,2%"
if "%TIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%TIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %DATE:~-4,4%%DATE:~0,2%%DATE:~3,2%_%HOUR:~-2%%TIME:~3,2%%TIME:~6,2%

的每个实例%DATE%%TIME%在其膨胀时将返回日期或时间值存在,因此第一%DATE%%TIME%表达可能返回比下述的不同的值(可以证明呼应含有巨大的这种量,preferrably一个长字符串时%TIME%,表达式)。

你可以改善上述代码保持的单个实例%DATE%%TIME%这样的:

rem // Store current date and time once in the same line:
set "CURRDATE=%DATE%" & set "CURRTIME=%TIME%"
rem // Resolve AM/PM time:
set "HOUR=%CURRTIME:~,2%"
if "%CURRTIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%CURRTIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %CURRDATE:~-4,4%%CURRDATE:~0,2%%CURRDATE:~3,2%_%HOUR:~-2%%CURRTIME:~3,2%%CURRTIME:~6,2%

但仍然,当在午夜执行时,%DATE%和中的返回值%TIME%可能反映不同的日期。

有当天的唯一途径%CURRDATE%%CURRTIME%是这样的:

rem // Store current date and time once in the same line:
set "CURRDATE=%DATE%" & set "CURRTIME=%TIME%"
rem // Resolve AM/PM time:
set "HOUR=%CURRTIME:~,2%"
if "%CURRTIME:~-2%" == "PM" if %HOUR% lss 12 set /A "HOUR+=12"
if "%CURRTIME:~-2%" == "AM" if %HOUR% equ 12 set /A "HOUR-=12"
rem // Fix date/time midnight discrepancy:
if not "%CURRDATE%" == "%DATE%" if %CURRTIME:~0,2% equ 0 set "CURRDATE=%DATE%"
rem // Left-zero-pad hour:
set "HOUR=0%HOUR%"
rem // Build and display date/time string:
echo %CURRDATE:~-4,4%%CURRDATE:~0,2%%CURRDATE:~3,2%_%HOUR:~-2%%CURRTIME:~3,2%%CURRTIME:~6,2%

当然,所描述的问题的发生是极不可能的,但是在某一时刻它将发生并引起奇怪的无法解释的故障。


不能与方法的基础上发生所描述的问题wmic中所描述的命令答复由用户斯蒂芬和在回答由用户PA。,因此我强烈建议您选择其中之一。的唯一缺点wmic是它的运行速度较慢。


0

我意识到这对OP来说是一个有争议的问题,但是我只是提出来了,我为自己在框外思考而感到自豪。

在以下网址下载适用于Windows的gawk网址http : //gnuwin32.sourceforge.net/packages/gawk.htm ...。然后它是一个衬里,没有笨拙的DOS批处理语法,它需要六个FOR循环来拆分字符串(WTF) ?那真的是坏妈妈和坏人!...当然是恕我直言)

如果您已经了解C,C ++,Perl或Ruby,那么选择AWK(它是从前两个继承而来,并为后两个做出了很大的贡献)是众所周知的CAKE!

DOS Batch命令:

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

印刷品:

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

现在这还不是完整的故事...我只是很懒,在printf语句中将其余的日志文件名硬编码,因为它很简单...但是,如果有人知道如何设置将%NOW%变量设置为AWK的输出(现在具有“通用”功能),我就不知所措。


编辑:

在Stack Overflow上的快速搜索填补了难题的最后一部分,即Bash backticks的Batch等效

因此,这三行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%

生产:

20120904-114434

因此,现在我可以在SQL Server安装(2005+)脚本生成的日志文件的名称中包含日期时间,因此:

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

而且我再次成为一个快乐的露营者(除非在Unix上生活仍然非常轻松)。


0

我喜欢在Stephan当前接受的答案上使用它,因为它可以在此之后使用命名参数配置时间戳:

for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x

它将提供以下参数:

  • 日间周
  • 小时
  • 毫秒
  • 分钟
  • 25美分硬币
  • 第二
  • WeekInMonth

然后,您可以像这样配置格式:

SET DATE=%Year%%Month%%Day%


0

因此,您想生成格式为date的日期YYYYMMDD_hhmmss。由于%date%%time%格式取决于语言环境,因此您可能需要更强大的方法来获取格式化日期。

这是一个选择:

@if (@X)==(@Y) @end /*
    @cscript //E:JScript //nologo "%~f0"
    @exit /b %errorlevel%
@end*/
var todayDate = new Date();
todayDate = "" + 
    todayDate.getFullYear() + 
    ("0" + (todayDate.getMonth() + 1)).slice(-2) +
    ("0" + todayDate.getDate()).slice(-2) + 
    "_" + 
    ("0" + todayDate.getHours()).slice(-2) +
    ("0" + todayDate.getMinutes()).slice(-2) +
    ("0" + todayDate.getSeconds()).slice(-2) ;
WScript.Echo(todayDate);

如果保存脚本,则jsdate.bat可以将其分配为值:

for /f %%a in ('jsdate.bat') do @set "fdate=%%a"
echo %fdate%

或直接从命令提示符处:

for /f %a in ('jsdate.bat') do @set "fdate=%a"

或者,您可以使用powershell,这可能是需要较少代码的方式:

for /f %%# in ('powershell Get-Date -Format "yyyyMMdd_HHmmss"') do set "fdate=%%#"

-1

文件名中的空格是合法的。如果将路径和文件名放在引号中,则可能会出现问题。这是我在批处理文件中使用的内容:

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

%filename%中是否有空格并不重要。


4
这与有关日期和时间的问题有什么关系?
jeb

有效问题。OP担心文件名中没有空格,但没有说明原因。这可能是出于美学原因。但是他们可能正在脚本中创建文件名,并且除非加引号,否则文件名中带有空格的文件名将被视为两个参数。
马蒂
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.