【问题标题】:Batch command date and time in file name文件名中的批处理命令日期和时间
【发布时间】:2011-12-05 08:11:29
【问题描述】:

我在命令行上使用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

但是,我的问题是 AMPM。 AM 时间戳给了我时间9(带有前导空格)与10 自然占用两个空格。

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

我该如何解决这个问题,以便包含前导零而不是前导空格,以便我得到Archive_20111011_093609.zip

【问题讨论】:

  • 我最终将你的用于日常任务,所有答案都更加混乱。

标签: windows batch-file command-line cmd


【解决方案1】:

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

您可以用 0 替换空白空间,例如 echo %time: =0%

但这仍然取决于,将该代码移动到其他随机位置的好友 PC 上,您会得到有趣的输出。所以可以合并powershell的Get-Date:

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

【讨论】:

    【解决方案2】:

    所以您想以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=%%#"
    

    【讨论】:

      【解决方案3】:

      我更倾向于在current accepted answer from Stephan 上使用它,因为它可以在之后使用命名参数配置时间戳:

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

      它将提供以下参数:

      • DayOfWeek
      • 小时
      • 毫秒
      • 分钟
      • 季度
      • 第二
      • WeekInMonth
      • 年份

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

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

      【讨论】:

      • 无论在 Windows 中是否有任何日期格式自定义或区域设置,这都能正常工作吗?
      【解决方案4】:

      另一种解决方案:

      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 期望反斜杠加倍,= 必须转义(第一个。第二个被引号保护) .

      【讨论】:

      • 太棒了! (wmic 命令的示例输出:LocalDateTime=20140619212037.828000+120
      • 不适合我%%I was unexpected at this time
      • @AnonymousMohit: %%I用于批处理文件。如果您直接在命令提示符下使用该行,则必须改用 %I
      • @Stephan 你知道如何以类似格式获取文件的“修改日期”吗?
      • @Logan:直到现在我才知道,但我找到了解决方案。查看我的编辑。
      【解决方案5】:

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


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

      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%
      

      当然,所描述的问题发生的可能性很小,但在某一时刻它会发生并导致奇怪的无法解释的故障。


      使用基于answer 用户Stephananswer 用户PA. 中描述的wmic 命令的方法不会出现所述问题,因此我强烈建议选择一个其中。 wmic 的唯一缺点是速度较慢。

      【讨论】:

        【解决方案6】:

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

        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(带有领先的空间和时间)。

        如果 PM 我得到20160915_2150101

        【讨论】:

        • 如果您添加 set d=%d: =0%,它将用零替换该空间。
        • 感谢 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% set d=%d: =0% echo hello>"Archive_%d%"
        • 如果有人想知道 "set d=%d: =0%" 会去哪里,它会在第 2 行和第 3 行之间
        【解决方案7】:

        正如 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
         )
        

        【讨论】:

          【解决方案8】:

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

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

          %filename% 中是否有空格无关紧要。

          【讨论】:

          • 这与日期和时间的问题有什么关系?
          • 有效问题。 OP 担心文件名中没有空格,但没有说明原因。这可能是出于审美原因。但他们可能会在脚本中创建文件名,并且其中包含空格的文件名将被视为两个参数,除非被引用。
          【解决方案9】:

          你应该搜索;您可以简单地将所有空格替换为零 set hr=%hr: =0% - jeb Oct 11 '11 at 14:16

          所以我做到了:

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

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

          (Jeb 在最受欢迎的答案下的评论对我来说效果最好,也是最简单的。我在这里重新发布它,以便将来的用户更清楚。)

          【讨论】:

          • 很遗憾您不能链接转换。 %time:~0,2: =0% 会很好。 :^(
          • 在我看来这似乎是最好的解决方案...我祝贺发送 WMIC 信息的人...主要是对我非常有用的独立日期格式“wmic os get localdatetime” .. 再次感谢大家...保持良好状态...
          • 哇真的很酷而且很短的解决方案。我不知道你可以像这样替换环境变量中的数字:D
          【解决方案10】:

          根据上面的回答,我做了一个现成的函数。

          通过法国本地设置验证。

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

          【讨论】:

            【解决方案11】:

            我意识到这对 OP 来说是一个没有实际意义的问题,但我只是在酝酿这个问题,我为自己跳出框框思考感到有点自豪。

            http://gnuwin32.sourceforge.net/packages/gawk.htm 处为 Windows 下载 gawk .... 然后它是单行的,没有所有笨拙的 DOS 批处理语法,它需要六个 FOR 循环来拆分字符串(WTF?这真的很糟糕悲伤!...恕我直言当然)

            如果您已经了解 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 的输出(放弃“通用”now 函数的胆量)然后我就全神贯注了。


            编辑:

            在 StackOverflow 上的快速搜索填补了最后一块拼图,Batch equivalent of 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 上的生活仍然非常轻松)。

            【讨论】:

              【解决方案12】:
              @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

              【讨论】:

                【解决方案13】:

                你的问题似乎已经解决了,但是……

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

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

                好吧,也许我错了。

                【讨论】:

                • 你刚刚与 1980 年的评论约会,老前辈。现在再读一遍我的问题,你会发现我从来没有提到我正在压缩任何代码。为了清楚起见,我正在归档 ETL 过程中使用的传入文件。
                • 是的,你从来没有提到你在压缩什么,这就是为什么我只是猜测。由于编码人员经常使用 SO,我错误地猜测它可能是代码。是的,我是一个老前辈(但这只是一个观点)
                【解决方案14】:

                您可以像这样批量添加前导零到变量(值最大为 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 的语言环境设置。我在我的公司服务器上执行此操作,更改区域设置在这些服务器上不是选项,所以我相当安全。日期+时间纯粹是作业运行时间的指示。
                【解决方案15】:

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

                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
                

                【讨论】:

                • 为什么要搜索,你可以简单地将所有空格替换为零set hr=%hr: =0%
                • @jeb,为什么评论而不回答?
                • 我收到了Archive_b-%a%cc-_142053.zip
                • @ZinanXing:因为此解决方案取决于本地设置(不同国家/地区的日期/时间字符串格式不同)。这就是为什么我更喜欢wmicsolution(请参阅我对这个问题的回答)
                猜你喜欢
                • 2023-03-17
                • 1970-01-01
                • 2015-07-16
                • 1970-01-01
                • 2023-03-04
                • 2018-03-09
                • 2015-02-28
                相关资源
                最近更新 更多