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

我正在命令行上使用 WinZip压缩文件。因为我们每天都存档,所以我尝试将日期和时间添加到这些文件中,这样每次都会自动生成一个新的文件。

我使用以下代码生成一个文件名。将其复制粘贴到命令行,您应该会看到一个包含 Date 和 Time 组件的文件名。

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 时间戳给了我时间 9(带有前导空格) ,而 10自然地占据了这两个空格。

我想我的问题也会延伸到前九天,前九个月等等。

如何修正这个问题,以便包含前导零而不是前导空格,从而得到 Archive_20111011_093609.zip

310061 次浏览

提取小时,寻找前导空格,如发现替换为零;

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

您可以像下面这样批处理一个变量(最大值为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

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

你的问题似乎解决了,但是..。

我不确定你是否采取了正确的解决方案。
我假设您每天都试图压缩实际的项目代码。

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

好吧,也许我错了。

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

一个用户可以将其系统配置为返回 Fri04081108.03 PM,而另一个用户可以选择08.04/201120: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
)
@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

我知道这对观察所来说是个无意义的问题,但我刚酿造了这个,我为自己跳出框框思考而感到有点自豪。

http://gnuwin32.sourceforge.net/packages/gawk.htm下载适用于 Windows 的 发呆..。然后它是一行程序,没有所有那些笨拙的 DOS 批处理语法,需要6个 FOR 循环来分割字符串(卧槽?这真是太糟糕了,疯狂和悲伤!... 恕我直言)

如果您已经知道 C、 C + + 、 Perl 或 Ruby,那么学习 AWK(它继承了前两者,并对后两者做出了重大贡献)就是众所周知的一块蛋糕! ! !

DOS 批处理命令:

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)

那么,这三行 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 set hr=%hr: =0%-Jeb 10月11日14:16

所以我照做了:

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

然后在格式化的字符串中使用 %hr%总是得到一个两位数的小时。

(杰布在最受欢迎的答案下的评论对我来说最有效,也是最简单的。我把它转发到这里,让它对未来的用户更加明显。)

另一个解决办法:

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希望反斜杠增加一倍,而 =必须转义(第一个)。第二个受到周围引号的保护)。

从上面的答案,我已经做了一个现成的使用功能。

用法国本地设置验证。

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

在读了你所有的答案后,我找到了最好的解决办法:

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

空格在文件名中是合法的。如果您将您的路径和文件名放在引号中,它可能只是飞行。下面是我在批处理文件中使用的内容:

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

文件名% 中是否有空格并不重要。

正如其他人已经指出的那样,%DATE%%TIME%(以及 date /Ttime /T)的日期和时间格式是依赖于地区的,因此提取当前的日期和时间总是一个噩梦,而且不可能得到一个适用于所有可能格式的解决方案,因为几乎没有任何格式限制。


但是像下面这样的代码还有另一个问题(让我们假设日期格式如 MM/DD/YYYY,12小时时间格式如 h:mm:ss.ff ap,其中 apAMPM,而 ff是小数秒) :

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%表达式可能返回与下列表达式不同的值(当回显包含大量此类表达式(最好是 %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命令的方法不会出现上述问题,因此我强烈建议使用其中之一。wmic的唯一缺点是它慢得多。

我经常在 目前接受斯蒂芬的回答上使用它,因为它可以在以后使用命名参数配置时间戳:

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

它将提供以下参数:

  • 白天
  • 每周一天
  • 一小时
  • 毫秒
  • 等一下
  • 月份
  • 25美分
  • 第二
  • 每周一个月
  • 年份

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

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

因此,您希望以 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=%%#"

在此答案列表中添加其他选项。

你可以用类似于 echo %time: =0%0代替空格

但这仍然是依赖的,移动代码到一个朋友的电脑在其他随机的地方,你会得到有趣的输出。所以你可以合并 Powershell 的 Get-Date:

for /f "tokens=*" %%i in ('PowerShell -Command "Get-Date -format 'yyyymmdd_HHmmss'"') do echo %%i.zip"