code

Windows 배치 : 형식화 된 날짜를 변수로

codestyles 2020. 8. 26. 07:53
반응형

Windows 배치 : 형식화 된 날짜를 변수로


현재 날짜를 YYYY-MM-DD 형식으로 Windows .bat 파일의 일부 변수에 저장하려면 어떻게합니까?

유닉스 쉘 아날로그 :

today=`date +%F`
echo $today

다음을 사용하여 로케일에 구애받지 않는 방식으로 현재 날짜를 가져올 수 있습니다.

for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x

그런 다음 하위 문자열을 사용하여 개별 부분을 추출 할 수 있습니다.

set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%

개별 부품을 포함하는 변수를 얻는 또 다른 방법은 다음과 같습니다.

for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%

변수 네임 스페이스를 오염시키는 대신 부분 문자열을 조작하는 것보다 훨씬 좋습니다.

현지 시간 대신 UTC가 필요한 경우 명령은 거의 동일합니다.

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

배치 파일에서 표준 MS-DOS 명령을 사용하여이 작업을 수행하려면 다음을 사용할 수 있습니다.

FOR /F "TOKENS=1 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%A
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2,3 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET yyyy=%%C

나는 이것이 추가로 개선 될 수 있다고 확신하지만 이것은 날짜를 일 (dd), 월 (mm) 및 연도 (yyyy)에 대한 3 개의 변수로 제공합니다. 그런 다음 필요에 따라 나중에 배치 스크립트에서 사용할 수 있습니다.

SET todaysdate=%yyyy%%mm%%dd%
echo %dd%
echo %mm%
echo %yyyy%
echo %todaysdate%

이 질문에 대한 답변이 수락되었음을 이해하지만 WMI 콘솔을 사용하지 않고이를 달성하려는 많은 사람들이이 대체 방법을 높이 평가할 수 있으므로이 질문에 가치를 더하기를 바랍니다.


날짜 / T를 사용하여 명령 프롬프트에서 형식을 찾습니다.

날짜 형식이 "Thu 03/03/2016"인 경우 다음과 같이 사용하십시오.

set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%

시간 설정에 의존하지 않는 두 가지 방법이 더 있습니다 (둘 다 현지화와 무관 한 데이터 / 시간 가져 오기에서 가져옴 ). 또한 둘 다 요일을 가져 오며 어느 것도 관리자 권한이 필요하지 않습니다! :

  1. MAKECAB- 모든 Windows 시스템에서 작동합니다 (빠르지 만 작은 임시 파일 생성) (foxidrive 스크립트) :

    @echo off
    pushd "%temp%"
    makecab /D RptFileName=~.rpt /D InfFileName=~.inf /f nul >nul
    for /f "tokens=3-7" %%a in ('find /i "makecab"^<~.rpt') do (
        set "current-date=%%e-%%b-%%c"
        set "current-time=%%d"
        set "weekday=%%a"
    )
    del ~.*
    popd
    echo %weekday% %current-date% %current-time%
    pause
    
  2. ROBOCOPY - Windows XPWindows Server 2003 의 기본 명령은 아니지만 Microsoft 사이트에서 다운로드 할 수 있습니다 . 그러나 Windows Vista 이상의 모든 기능에 내장되어 있습니다.

    @echo off
    setlocal
    for /f "skip=8 tokens=2,3,4,5,6,7,8 delims=: " %%D in ('robocopy /l * \ \ /ns /nc /ndl /nfl /np /njh /XF * /XD *') do (
        set "dow=%%D"
        set "month=%%E"
        set "day=%%F"
        set "HH=%%G"
        set "MM=%%H"
        set "SS=%%I"
        set "year=%%J"
    )
    
    echo Day of the week: %dow%
    echo Day of the month : %day%
    echo Month : %month%
    echo hour : %HH%
    echo minutes : %MM%
    echo seconds : %SS%
    echo year : %year%
    endlocal
    

    다른 Windows 스크립트 언어를 사용하는 세 가지 방법이 더 있습니다. 예를 들어 주, 시간 (밀리 초) 등을 얻을 수 있습니다.

  3. JScript / BATCH 하이브리드 (으로 저장해야 함 .bat). JScript는 Windows 스크립트 호스트 의 일부로 Windows NT 이상의 모든 시스템에서 사용할 수 있습니다 ( 드문 경우지만 레지스트리를 통해 비활성화 할 수 있음 ).

    @if (@X)==(@Y) @end /* ---Harmless hybrid line that begins a JScript comment
    
    @echo off
    cscript //E:JScript //nologo "%~f0"
    exit /b 0
    *------------------------------------------------------------------------------*/
    
    function GetCurrentDate() {
        // Today date time which will used to set as default date.
        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);
    
        return todayDate;
    }
    
    WScript.Echo(GetCurrentDate());
    
  4. VBScript / BATCH 하이브리드 ( 임시 파일을 사용하지 않고 배치 파일 내에 VBScript를 삽입하고 실행할 수 있습니까? ) jscript와 동일한 경우이지만 하이브리드 화는 그렇게 완벽하지 않습니다.

    :sub echo(str) :end sub
    echo off
    '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul
    '& echo current date:
    '& cscript /nologo /E:vbscript "%~f0"
    '& exit /b
    
    '0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if specified: hh:mm:ss PM/AM.
    '1 = vbLongDate - Returns date: weekday, monthname, year
    '2 = vbShortDate - Returns date: mm/dd/yy
    '3 = vbLongTime - Returns time: hh:mm:ss PM/AM
    '4 = vbShortTime - Return time: hh:mm
    
    WScript.echo  Replace(FormatDateTime(Date, 1), ", ", "-")
    
  5. PowerShell-.NET 이있는 모든 컴퓨터에 설치할 수 있습니다. Microsoft ( v1 , v2v3 (Windows 7 이상에만 해당)) 에서 다운로드 할 수 있습니다 . Windows 7 / Win2008 이상의 모든 형식에 기본적으로 설치됩니다.

    C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
    
  6. 자체 컴파일 된 jscript.net/batch(.NET 이없는 Windows 시스템을 본 적이 없으므로 이식성이 매우 좋다고 생각합니다) :

    @if (@X)==(@Y) @end /****** silent line that start jscript comment ******
    
    @echo off
    ::::::::::::::::::::::::::::::::::::
    :::       Compile the script    ::::
    ::::::::::::::::::::::::::::::::::::
    setlocal
    if exist "%~n0.exe" goto :skip_compilation
    
    set "frm=%SystemRoot%\Microsoft.NET\Framework\"
    :: searching the latest installed .net framework
    for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
        if exist "%%v\jsc.exe" (
            rem :: the javascript.net compiler
            set "jsc=%%~dpsnfxv\jsc.exe"
            goto :break_loop
        )
    )
    echo jsc.exe not found && exit /b 0
    :break_loop
    
    
    call %jsc% /nologo /out:"%~n0.exe" "%~dpsfnx0"
    ::::::::::::::::::::::::::::::::::::
    :::       End of compilation    ::::
    ::::::::::::::::::::::::::::::::::::
    :skip_compilation
    
    "%~n0.exe"
    
    exit /b 0
    
    
    ****** End of JScript comment ******/
    import System;
    import System.IO;
    
    var dt=DateTime.Now;
    Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss"));
    
  7. Logman 이것은 년과 요일을 가져올 수 없습니다. 비교적 느리고 임시 파일도 생성하며 logman이 로그 파일에 기록한 타임 스탬프를 기반으로하며 Windows XP 이상에서 모든 작업을 수행합니다. 아마 저를 포함하여 누구도 사용하지 않을 것입니다. 그러나 그것은 또 하나의 방법입니다 ...

    @echo off
    setlocal
    del /q /f %temp%\timestampfile_*
    
    Logman.exe stop ts-CPU 1>nul 2>&1
    Logman.exe delete ts-CPU 1>nul 2>&1
    
    Logman.exe create counter ts-CPU  -sc 2 -v mmddhhmm -max 250 -c "\Processor(_Total)\%% Processor Time" -o %temp%\timestampfile_ >nul
    Logman.exe start ts-CPU 1>nul 2>&1
    
    Logman.exe stop ts-CPU >nul 2>&1
    Logman.exe delete ts-CPU >nul 2>&1
    for /f "tokens=2 delims=_." %%t in  ('dir /b %temp%\timestampfile_*^&del /q/f %temp%\timestampfile_*') do set timestamp=%%t
    
    echo %timestamp%
    echo MM: %timestamp:~0,2%
    echo dd: %timestamp:~2,2%
    echo hh: %timestamp:~4,2%
    echo mm: %timestamp:~6,2%
    
    endlocal
    exit /b 0
    

Get-Date 함수에 대한 자세한 정보 .



나는 Joey의 방법을 정말 좋아했지만 조금 더 확장 할 것이라고 생각했습니다.

이 접근 방식에서는 코드를 여러 번 실행할 수 있으며 이전 날짜 값이 이미 정의되어 있기 때문에 "고착"되는 것에 대해 걱정할 필요가 없습니다.

이 배치 파일을 실행할 때마다 ISO 8601 호환 날짜 및 시간 표현이 출력됩니다.

FOR /F "skip=1" %%D IN ('WMIC OS GET LocalDateTime') DO (SET LIDATE=%%D & GOTO :GOT_LIDATE)
:GOT_LIDATE
SET DATETIME=%LIDATE:~0,4%-%LIDATE:~4,2%-%LIDATE:~6,2%T%LIDATE:~8,2%:%LIDATE:~10,2%:%LIDATE:~12,2%
ECHO %DATETIME%

In this version, you'll have to be careful not to copy/paste the same code to multiple places in the file because that would cause duplicate labels. You could either have a separate label for each copy, or just put this code into its own batch file and call it from your source file wherever necessary.


Just use the %date% variable:

echo %date%

As per answer by @ProVi just change to suit the formatting you require

echo %DATE:~10,4%-%DATE:~7,2%-%DATE:~4,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%

will return

yyyy-MM-dd hh:mm:ss
2015-09-15 18:36:11

EDIT As per @Jeb comment, whom is correct the above time format will only work if your DATE /T command returns

ddd dd/mm/yyyy
Thu 17/09/2015

It is easy to edit to suit your locale however, by using the indexing of each character in the string returned by the relevant %DATE% environment variable you can extract the parts of the string you need.

eg. Using %DATE~10,4% would expand the DATE environment variable, and then use only the 4 characters that begin at the 11th (offset 10) character of the expanded result

For example if using US styled dates then the following applies

ddd mm/dd/yyyy
Thu 09/17/2015

echo %DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%
2015-09-17 18:36:11

I set an environment variable to the value in the numeric format desired by doing this:

FOR /F "tokens=1,2,3,4 delims=/ " %a IN ('echo %date%') DO set DateRun=%d-%b-%c

Check this one..

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%" & set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%-%MS%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
pause

It is possible to use PowerShell and redirect its output to an environment variable by using a loop.

From the command line (cmd):

for /f "tokens=*" %a in ('powershell get-date -format "{yyyy-mm-dd+HH:mm}"') do set td=%a

echo %td%
2016-25-02+17:25

In a batch file you might escape %a as %%a:

for /f "tokens=*" %%a in ('powershell get-date -format "{yyyy-mm-dd+HH:mm}"') do set td=%%a

If you have Python installed, you can do

python -c "import datetime;print(datetime.date.today().strftime('%Y-%m-%d'))"

You can easily adapt the format string to your needs.


Due to date and time format is location specific info, retrieving them from %date% and %time% variables will need extra effort to parse the string with format transform into consideration. A good idea is to use some API to retrieve the data structure and parse as you wish. WMIC is a good choice. Below example use Win32_LocalTime. You can also use Win32_CurrentTime or Win32_UTCTime.

@echo off  
SETLOCAL ENABLEDELAYEDEXPANSION  
for /f %%x in ('wmic path Win32_LocalTime get /format:list ^| findstr "="') do set %%x  
set yyyy=0000%Year%  
set mmmm=0000%Month%  
set dd=00%Day%  
set hh=00%Hour%  
set mm=00%Minute%  
set ss=00%Second%  
set ts=!yyyy:~-4!-!mmmm:~-2!-!dd:~-2!_!hh:~-2!:!mm:~-2!:!ss:~-2!  
echo %ts%  
ENDLOCAL  

Result:
2018-04-25_10:03:11


echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 

This is an extension of Joey's answer to include the time and pad the parts with 0's.

For example, the result will be 2019-06-01_17-25-36. Also note that this is the UTC time.

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

  set Month=0%Month%
  set Month=%Month:~-2%
  set Day=0%Day%
  set Day=%Day:~-2%
  set Hour=0%Hour%
  set Hour=%Hour:~-2%
  set Minute=0%Minute%
  set Minute=%Minute:~-2%
  set Second=0%Second%
  set Second=%Second:~-2%

  set TimeStamp=%Year%-%Month%-%Day%_%Hour%-%Minute%-%Second%

If you don't mind an one-time investment of 10 to 30 minutes to get a reliable solution (that doesn't depend on Windows' region settings), please read on.

Let's free our minds. Do you want to simplify the scripts to just look like this? (Assume you wants to set the LOG_DATETIME variable)

FOR /F "tokens=* USEBACKQ" %%F IN (`FormatNow "yyyy-MM-dd"`) DO (
  Set LOG_DATETIME=%%F
)

echo I am going to write log to Testing_%LOG_DATETIME%.log

You can. Simply build a FormatNow.exe with C# .NET and add it to your PATH.

Notes:

  1. You can use any Visual Studio edition, such as Visual Studio Express, to build the FormatNow.exe.
  2. In Visual Studio, choose the "Console Application" C# project, not "Windows Forms Application" project.
  3. Common sense: the built FormatNow.exe will need .NET Framework to run.
  4. Common sense: after adding FormatNow.exe to PATH variable, you need to restart CMD to take effect. It also applies to any change in environment variables.

Benefits:

  1. It's not slow (finishes within 0.2 seconds).
  2. Many formats are supported https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx e.g. FormatNow "ddd" to get only the day of week, FormatNow "yyyy" to get only the year
  3. It doesn't depend on Windows' region settings, so its output is much more reliable. On the other hand, %date% doesn't give a consistent format over different computers, and is not reliable.
  4. You don't need to create so many CMD variables and pollute the variable namespace.
  5. It would require 3 lines in the batch script to invoke the program and get the results. It should be reasonably short enough.

Source code of FormatNow.exe which I built with Visual Studio 2010 (I prefer to build it myself to avoid the risk of downloading an unknown, possibly malicious program). Just copy and paste the codes below, build the program once, and then you have a reliable date formatter for all future uses.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace FormatNow
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 1)
                {
                    throw new ArgumentException("Missing format");
                }
                string format = args[0];
                Console.Write(DateTime.Now.ToString(format, CultureInfo.InvariantCulture.DateTimeFormat));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

    }
}

In general, when dealing with complicated logics, we can make it simpler for by building a very small program and calling the program to capture the output back to a batch script variable instead. We are not students and we're not taking exams requiring us to follow the batch-script-only rule to solve problems. In real working environment, any (legal) method is allowed. Why should we still stick to the poor capabilities of Windows batch script that needs workarounds for many simple tasks? Why should we use the wrong tool for the job?

참고URL : https://stackoverflow.com/questions/10945572/windows-batch-formatted-date-into-variable

반응형