Blog du Tristank

So terrific that 3 of 4 readers rated it "soporific"

Blogs

one-Line Iso-Ish-Date Format Thing For CMD

  • Comments 14
  • Likes

I love CMD. I love batch files. I love FOR. I love being able to do things in one line, without resorting to VBScript or a custom EXE.

Today's task: make a unique folder for each day of metabase collection. I figured that getting a folder-creation-capable date format out of %date% and %time% should be reasonably easy somehow, so investigated non-FOR options but nothing really worked. Back to FOR it is!

I then figured that if you wanted to collect data more often than daily, you could probably add the time in without too much trouble, so did that too.

As a warning, this won't localize directly: Yank-To-ISO-ish format is %%k%%i%%j-%%l%%m , for example.

@echo off
for /f "tokens=2,3,4,5,6 delims=:./ " %%i in ("%date%.%time%") do SET isodate=%%k%%j%%i-%%l%%m
 
md c:\logs\%isodate%

REM now do whatever...
Copy C:\Windows\System32\inetsrv\History c:\logs\%isodate%

To play around with FOR commands on the command line, you don't need to double the % signs, so:

for /f "tokens=2,3,4,5,6 delims=:./ " %i in ("%date%.%time%") do @echo %k%j%i-%l%m

Again: Localization or customization is needed if you're in a non-Brit-style (day, month, year) locale, or if your short date doesn't look like mine. For reference (think I'm at Australian defaults):

C:\Tools>echo %date%
Thu 20/07/2006

C:\Tools>echo %time%
20:12:56.55

Um, that's all I had to share right now. Be fruitful and collect logs!

--

The Revised Efficientified Edition (Edits from (and thanks to) Kiliman)

Two lines, using SET statements, get a pretty reliable outcome. At first I was getting weird results, then realized that copy/paste had appended a space to a couple of the lines - if there's a space at the end of any SET statement, it can come back later to cause weirdness.

@echo off
rem Be careful to not leave a trailing space
rem at the end of any SET line below
 
rem -- for US Date Format
rem SET isodate=%DATE:~10%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%%TIME:~3,2%
 
rem -- for AU/UK Date Format
SET isodate=%DATE:~10%%DATE:~7,2%%DATE:~4,2%-%TIME:~0,2%%TIME:~3,2%

rem replace space with 0
SET isodate=%isodate: =0%
md c:\logs\%isodate%

rem now do whatever...
Copy C:\Windows\System32\inetsrv\History c:\logs\%isodate%

Thanks to all that share(d) their expertise in the comments area.

Comments
  • How about this?

    Using DD/MM Format:
    SET isodate=%DATE:~10%%DATE:~7,2%%DATE:~4,2%-%TIME:~0,2%%TIME:~3,2%

    Using MM/DD Format:
    SET isodate=%DATE:~10%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%%TIME:~3,2%

  • I'm sorry, can you rephrase your answer IN THE FORM OF A POWERSHELL SCRIPT, BEEYOTCH?!

    CMD.exe is dead to me.

    Plus, all the cool people are doing it. And you want to be cool. Don't you? Eh? Don't you?!

  • Ah sweet FOR command, so many wonderful memories. What can't you do with the FOR command? Probably not bring about world peace or save users from themselves but it would come close..

  • Kiliman - that's amazing. I had no idea!

    isodate=20060721- 933

    Any idea if you can subsitute a padding character for that leading zero in the time (and I'm guessing for the date when it hits 1/08/2006)?


    Jeff, me old salt, me old mate, me old... bad grammar buddy...

    Yeah, I'd have tried it in PowerShell, except that PowerShell is the future, and working as I do on the trailing edge of technology adoption, I'm constantly looking for solutions that work across at least a couple of OS versions with no added bells or whistles.

    Plus, I'm going to need to spend more time with Powershell before I'm confident - my last set of attempts to do something I thought would be quite straightforward resulted in about three hours' fiddling before I gave up. I think the cause was a bug, but when using betas and with no actual confidence in your hastily-acquired JIT knowledge, you can never be sure. (the JITter's dilemma?)

    I hereby cite the <a href="http://www.codinghorror.com/blog/archives/000382.html">customization dilemma</a> you wrote about - I have to assume that customers
    a) have only the tools we provide them in the base OS or
    b) I tell them to install (assuming they agree!)

    Frequently there's customer resistance to installing new stuff, especially on servers, which is understandable. Getting from base OS to .Net 2.0 to Powershell is an argument I can do without.

    It might be fun the first time, but if you multiply that out at a rate of one per case, it's not worth it for a pretty folder name. Likewise - I could write an ISODATE.exe that would do the job very efficiently and cover all sorts of date formats... but then I'd have to get every customer to use this EXE, and emailing EXEs is dodgy at best, and so on...

  • I don't use the time portion in my batch scripts, so I kind of tacked the time part in as an afterthought. Unfortunately, it was in the afternoon, so I didn't notice that the time doesn't include the leading 0.

    I did verify that at least for the date, it does include the leading 0 for single digit days and months.

    Another way to do it is to use Windows Scripting. Unfortunately, cscript.exe doesn't provide a way to pass in statements that will be evaluated directly from the command line, like Perl for example (perl -e).

    So basically you can "echo" the VBScript statements to a temp file, then use FOR /F to get the results that you can use to set your enviroment variable.

    This is a definite kludge, but it's a general technique you can use when cmd.exe just won't do, and doesn't rely on adding any new tools or extra files to the end users' system.

    I'm not sure how the following will wrap, so I separated each line with a blank line. Note that I used "+" instead of "&" for string concatenation. This is because CMD.EXE interprets the & as a command separator and unfortunately you can't escape it from the echo statement.

    ----8<---- snip here --->8----

    echo WScript.Echo CStr(Year(Now)) + Right("00" + CStr(Month(Now)), 2) + Right("00" + CStr(Day(Now)), 2) + "-" + Right("00" + CStr(Hour(Now)), 2) + Right("00" + CStr(Minute(Now)), 2) > %TEMP%\isodate.vbs

    for /f "usebackq" %%i in (`cscript //nologo %TEMP%\isodate.vbs`) do set isodate=%%i

    echo %isodate%

    ----8<---- snip here --->8----

    Kiliman

  • > Frequently there's customer resistance to installing new stuff, especially on servers, which is understandable. Getting from base OS to .Net 2.0 to Powershell is an argument I can do without.

    Well, the obvious answer is to get rid of those annoying customers. I mean, obviously.

  • re the afterthought - hey, so did I! - I was originally shooting for daily, but then figured I could - how you say? - have my cake twice. Maybe more!

    Next: good GRIEF! That is a really impressive kludge!

    I'm sitting here playing with the Windows Vista command prompt (oh look! it's 3:42 AM, I really should go to sleep, but it's convenient for playing with this), and notice that with my current settings, %time% is always left-padded by one character. Luckily, consecutive token characters seem to be skipped, so the original works.

    So many assumptions, but such fun! (Using PROMPT $P $D $T$G for fun)

    G:\Users\Tristank Sat 22/07/2006  3:41:26.59>echo %date%.0%time%
    Sat 22/07/2006.0 3:41:36.15

    G:\Users\Tristank Sat 22/07/2006  3:42:02.70>echo %date%.%time%
    Sat 22/07/2006. 3:42:07.64

    G:\Users\Tristank Sat 22/07/2006  3:42:07.64>echo %time%
    3:42:25.09

    Trying to avoid temp files, I was playing with using the %name:~-x,y% syntax on a padded FOR variable, but it looks like they don't work in the same way. I could use more lines and no vbscript to get the job done, but I think I've just sailed past the edge of Costa Benefita Pier, and I'm going to call it a night! :) Perhaps *one more* game of BF2 Modern Combat...

  • Drat! It's so simple!

    Jeff, when you finally publish your book on World Domination CodingHorror Stylez, I promise I will be first in line to queue up.

    Now, where did I leave my lay-zerrr?

  • for /f "tokens=2-6...
    is much cleaner than trying to list them all out.

    I have a batch script that has been used in backing up our sql server databases for a number of years. Not knowing the trailing 4 characters (no -) was the time, I wildcarded the remainder of the file since all I needed was the date. This is the first time all of what I put in the batch file makes sense, as I think I just ripped it from an example on manipulating the date command.

  • It turns out that SET has the ability to search and replace.

    Since %TIME% has a leading space if hour is less than 10, we can use the following to convert the space to a 0.

    rem get isodate from MM/DD format
    set isodate=%DATE:~10%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%%TIME:~3,2%

    rem replace space with 0
    set isodate=%isodate: =0%

    echo %isodate%

    Enjoy!

    Kiliman

  • Jeremy: thanks!
    Kiliman: now that looks pretty kick-donkey! Can't wait to try it out too!

  • While we are on batch scripting, does anyone know what this means when seen in a script:

    set test=%1
    set test=%test:"=%

    Obviously %1 is a parameter being passed to the variable, but what does the :"= bit mean in the second line?

  • Jodee: run set /? in cmd, and you shall see the truth.

    In our case:
    %test    - value of test
    :            - but...
    "            - all occurances of the character "
    =           - should be replaced with...
    (nothing) - nothing
    %          - and that's it.


    I guess it's a way to un-quote a quoted param. If it's a parameter (%1), you could just use %~1 to accomplish the same thing. This is even documented in \windows\help\ntcmds.chm.

  • DOS: The world changes - the world stays the same.

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment