From ts@uwasa.fi Thu Mar  6 00:00:00 2008
Subject: General information of this script tricks file package
Date: Thu,  6 Mar 2008 00:00:00
From: ts@uwasa.fi (Timo Salmi)

Assorted NT/2000/XP CMD.EXE Script Tricks             Thu 6-Mar-2008
=========================================
                                                 All rights reserved
                               Copyright (c) 2003-2008 by Timo Salmi

....................................................................
Prof. Timo Salmi   Co-moderator of news:comp.archives.msdos.announce
Moderating at ftp:// & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance  ; University of Vaasa
mailto:ts@uwasa.fi <http://www.uwasa.fi/~ts/>  ; FI-65101,   Finland
Dense spam-kill procmail filtering with a public email key in effect
....................................................................

  +-----------------------------------------------------------+
  | This file belongs to TSCMD*.ZIP. Please do not distribute |
  | this 1CMDFAQ.TXT file separately! If you see this file    |
  | reproduced alone, please alert the SysAdmin immediately.  |
  +-----------------------------------------------------------+

 ftp://garbo.uwasa.fi/pc/link/tscmd.zip
 Useful NT/2000/XP script tricks and tips, T.Salmi
 Http link format http://garbo.uwasa.fi/pub/pc/link/tscmd.zip

Introduction
============

DESCRIPTION:  This  file contains assorted CMD.EXE script tricks for
Windows NT/2000/XP. The items are in no particular order.  There  is
some overlap in some of the items.

QUOTING:  You are free to quote brief passages from this 1CMDFAQ.TXT
file in your messages and postings provided you clearly indicate the
source.  If you do, the preferred pointer to me in such a connection
is "Prof. Timo Salmi of the University of Vaasa, Finland". Note that
the  contents,  as  well  as  the  index composition of the question
items, fully remains Timo Salmi's copyright.

WEB PAGES OR ANY OTHER REPRODUCTION: No part of this  material,  nor
its  index,  nor  the entire contents of this file may be reproduced
(in any language) on any World Wide  Web  pages  (with  the  natural
exception  of  straight  Usenet  news repository services) or in any
other electronic, physical or similar manner.

ASKING FOR ADVICE: Comments and corrections are  solicited.  But  if
you  wish to have individual script programming consultation, please
rather   post   your   question   to   a   Usenet   newsgroup   like
news:alt.msdos.batch.nt  .  It is much more efficient than asking me
by email. I'd like to help, but I am very pressed for time. I prefer
to  pick  the  questions  I  answer from the Usenet news. Thus I can
answer publicly at one go if I happen to have  an  answer.  Besides,
newsgroups  have  a  number of readers who might know a better or an
alternative answer. Don't be discouraged, though, if you get a reply
like  this  from  me.  I am always glad to hear from friendly fellow
script file users.  For more on this aspect in a web page format see
  I need your advice with this programming problem
  http://www.uwasa.fi/~ts/garbinfo/garb3020.html

EMAIL FILTERED: Please be aware that because of the  huge  spam  and
other  problems on the Internet my email is strictly protected by an
elaborate filtering system requiring a password from non-whitelisted
users,  and discarding many sources. For those interested in further
details: http://www.uwasa.fi/~ts/info/spamfoil.html

CONTRIBUTORS: A FAQ-like collection always is more or less a product
of  collective  knowledge.  The initial origins of many of the ideas
are often ambiguous and  may  have  been  discovered  separately  by
several  authors.  Thus  a  collective  thanks  for  the  NT/2000/XP
scripting community is in order. Furthermore, at least the following
individuals   have  either  directly  contributed  to  or  otherwise
knowingly or unknowingly influenced the contents of this  FAQ  in  a
positive manner:

  Allen, William
  Ballenger, Si
  Briscoe, Walter
  Calvert, Clay
  Davis, Ted
  Dunbar, Al
  Dye, Charles
  Grove, Harlan
  Hardy, Steve
  Kasal, Stepan
  Kleebauer, Herbert
  Lawrence, Ritchie
  Meinhard, Klaus
  Prins, Robert
  Robyn, Phil
  Said, Marco Maier
  Smith, Gary L.
  Smith, Paul
  Stockton, John
  Stewart, Bill
  Suhovey, Alexander
  Tacke, Matthias
  Takashi, Ootani
  Vargo, Todd

SUBMITTING: Although feedback is welcome and this NT/2000/XP command
line script programming tricks and  files  collection  has  FAQ-like
features,  it  is not meant as a composition of collective knowledge
from various quarters. All the items in this collection are to be my
own  work. Thus you can't submit your own items into this collection
despite the feedback being welcome. (Feedback on the Usenet news  is
strongly  preferable  over  emailed  feedback.) However, there is an
item (#21) about additional sources of information.

REFERENCES/COMMENTS:  Many  items   contain   "References/comments:"
mainly  to  Usenet  news  postings stored at Google. These items are
there either as a historical  record  or  for  further,  interesting
readings. Nevertheless, this tscmd.zip NT/2000/XP CMD.EXE script FAQ
collection  is  a  self-contained  entity.  Please  note  that   the
reference  paths  to e.g. Google messages might have changed because
of the repository's system developments. I am not  going  to  second
guess  them.  My  originals  and  their Message-Ids will have to do.
(Find the message with the id 476f5d9d$0$14994$9b536df3@news.fv.fi )

OTHER RESOURCES: See item "21} Do you have  pointers  to  additional
script  material  and  tips?  Also see the included TSPROG.TXT file.
Furthermore, this collection has a sister FAQ  for  MS-DOS  batches.
Most  of  the  tricks there are directly applicable to Win..95/98/Me
and some of the items are  applicable  to  NT/2000/XP  command  line
script programming as well. The file in question is

 ftp://garbo.uwasa.fi/pc/link/tsbat.zip
 Useful MS-DOS batch files and tricks, T.Salmi

DISCLAIMER: The author shall not be  liable  to  the  user  for  any
direct,  indirect  or consequential loss arising from the use of, or
inability to use, any information, program, script or file howsoever
caused.  No  warranty is given that the scripts, the programs or the
advice given will work under all circumstances.
--------------------------------------------------------------------

Caveats
=======

The scripts in this FAQ have been tested on a Windows XP [Version
5.1.2600] Professional Edition, SP2, system, which adds some new
features to script commands and their parameters. Mostly, no attempt
has been or will be made to identify which features might be novel
compared to the earlier (factual) NT versions, or later Windows
operating systems. Thus there is no guarantee that all the solutions
are fully backwards, or forwards, compatible.

The code page used in testing and using the scripts has been 850.
The default language affects some of the script formulations and
outcomes such as the date and time formats. If you wish to emulate
this behavior put the following line near the top of your scripts:
  mode con: codepage select=850
Once you do it, it will stay in user-wide effect, until you change
it again. Cf. Item #11 for more details. Note that, depending on the
case, setting the codepage might not be enough. The Windows (Control
Panel) Regional Settings and the script particulars will have to
agree. Some customization may be required where either date, time,
currency or decimal conventions are involved.

The date/time format assumed is "31.01.2005 14:12:18". In other
words, the order is DD.MM.YYYY, the date separator is ".", the
timefields separator is ":" and the 24 hour format is assumed. If
yours differ either adjust the scripts where needed, or change your
defaults via
 Start
  Settings
   Control Panel
    Regional and Language Options
     Time:
     Short date:

Two very common external auxiliary programs are used in a few of the
solution versions presented. It is highly recommended anyway that
you obtain the following utilities:

GAWK.EXE A Pattern Scanning and Processing Language
 233923 Mar 25 1995 ftp://garbo.uwasa.fi/pc/unix/gawk2156.zip
 GNU awk text scanning and processing language
Be forewarned. If you use a different GAWK its syntax requirements
may slightly differ. See the example in item #6.

SED.EXE Stream Editor
 20368 Oct 1 1991 ftp://garbo.uwasa.fi/pc/unix/sed15x.zip
 HHSED executable, E.Raymond+D.Kirschbaum+H.Helman
 (Note, I use these older versions)

A few words about the philosophy of using gawk and sed solutions:
http://www.google.com/groups?selm=akkesb%24itn%40poiju.uwasa.fi
http://www.google.com/groups?selm=42612883%241_1%40news.dnainternet.net
However, some of these tricks might be conceivable in a multi-user
setting where it is best to assume that only the native commands are
available. Therefore, the usage of any extra tools is avoided as the
only option much as reasonable.

Visual Basic Script can be used to solve some, if not most of the
scripting problems. The same goes for QBASIC. However, not all the
items which could have been solved with Basic aided command line
scripts include the option. This is above all CMD.EXE scripting FAQ,
not a VBS or QBASIC FAQ.

A number of date-related items and routines are included.
Date-related standards and calculations can be quite involved.
Therefore, not all the refinements are fulfilled in the strictest
sense. To give one example, one item is about the date a certain
number of days ago. The effect of a potential daylight saving time
("summertime") shift is ignored. Thus the result might be off by one
day near the midnight under special circumstances. Likewise,
timezone differences are ignored. A reader requiring more accurate
knowledge is referred to the web pages by Dr. John Stockton which
can be found by starting at http://www.merlyn.demon.co.uk/index.htm#dat
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:00 2008
Subject: Script tricks index
Date: Thu,  6 Mar 2008 01:00:00
From: ts@uwasa.fi (Timo Salmi)

INDEX
=====

1}  How to get today's date elements into environment variables?
2}  On Windows XP how do you stop the script files from closing?
3}  How can I customize the Command Prompt Window with script commands?
4}  How can I test is it on MSDOS/Win3..9x/Me or NT/2000/XP?
5}  How do I get a fully qualified path name of my script?
6}  How does one get yesterday's date?
7}  How can I test if two files agree in size and datetime stamp?
8}  How do I find all the files made at of after YYYYMMDD HHMM?
9}  How can I suppress script error messages altogether?
10} How can I change the environment variable values within a FOR loop?
11} How do I retain my original code page in these scripts?
12} How can I rename all my .JPG files sequentially in a folder?
13} How do I get the current day of the week?
14} Help! My old batch files won't work since there is no choice.com
15} Is it possible to echo without linefeed like the Unix echo -n?
16} How can I get the time without having to press enter?
17} How can I avoid the potential "ECHO is off." in echoing %myvar%
18} How does one build re-usable script function modules?
19} How can one build a delay / sleep / wait procedure for a script?
20} Is is possible to right-justify numbers or words in a script?
21} Do you have pointers to additional script material and tips?
22} How do I capture the current folder name into a variable?
23} How do I get the n'th, the first and the last line of a text file?
24} How do I get the m'th item on the n'th line of a text file?
25} How can I quote with e.g. "> " an entire message?
26} How do I get the length of a string into a variable?
27} How can I remove all the blank lines from a text file?
28} How to convert a file written in IBM PC characters into LATIN1?
29} How do I drop the first two characters of a string, and so on?
30} Can one calculate the difference between two times in a script?
31} How many days ago was 31.12.2003? What date was it 100 days ago?
32} How can I convert a decimal number to binary, octal, hexadecimal?
33} How can I convert a binary, octal, hexadecimal into a decimal?
34} How can I remove the quote characters from a line?
35} How can I substitute the second field on each line of my file?
36} I start a program from my script and it hogs my command window.
37} How can I insert a line in the middle of a file with a script?
38} How can I set and test the errorlevel within a script file?
39} Is there a subroutine to convert a variable into uppercase?
40} How to get the number of and parse the arguments given to a script?
41} How can I create a zero-byte file? How do I test for it?
42} What is the subroutine for testing a filename for wildcards?
43} Is there a way of counting the number of files in a folder?
44} How do I get the first 68 columns from a text file?
45} How can I find out how many days old a file is?
46} Is a program available in the default folder or at path?
47} Is it possible to echo the redirection symbol in a script?
48} Why do some comment lines cause errors? What can I do about it?
49} I need to reverse a text file. How do I do that fairly quickly?
50} How do I get the position of a substring in a string?
51} How can I echo lines in different colors in NT scripts?
52} How can I enter a password into a variable without echoing it?
53} How can I quietly test if a disk device is ready or not?
54} How can I get the type of a disk device?
55} How to get the creation, last modified and last access of a file?
56} How to find and move more recent files from one folder to another?
57} How do I get a list of all my empty folders on c:\ ?
58} How do I best combine two quoted arguments into one quoted string?
59} How do I find if a folder exists? How about visible files in it?
60} How do I delete all but most recent 20 files in a folder?
61} How can one devise a command line calculator?
62} How can I compare within a script if two files are identical?
63} How to perform a command on each line of a file as an argument?
64} How to count the number of lines in a file, empty lines inclusive?
65} How do I add text in front and after each line in a text file?
66} How can I delete all the hidden Thumbs.db files from my system?
67} Is it possible to send a script variable value to the clipboard?
68} How can I test if a program already has been loaded?
69} How do I get the first, or the last, 400 lines of a file?
70} Calendar: What weekday was December 31, 2004?
71} How can I reboot my computer from a command line script?
72} Is it possible to use quotes as delims in for loops?
73} How can I convert a hexadecimal string into an ASCII string?
74} How can I compare two numbers that have decimals with IF?
75} How do I detect if an object is a file or a folder?
76} How do I create an empty file? How can I detect the empty files?
77} How do I list the files in \All Users\Desktop in the short format?
78} Is it possible automatically to record my logon times into a file?
79} How can I trim leading and trailing spaces?
80} How can I extract the last part of a path such as C:\ABC\DEF\GHI\?
81} Is there a script to capitalize all the words in a text file?
82} Why does echo 9>temp.txt fail while echo 10>temp.txt works?
83} How to archive files with a rotation of five latest generations?
84} How can I automate downloading files from an ftp-site?
85} How to test if a folder contains any files with long names?
86} How to put each line of a text file into an environment variable?
87} How can I create a four-digit random string?
88} How to convert DEC to HEX with a script file, and vice versa?
89} All of a sudden "echo." doesn't work any more. What's wrong?
90} How do I get the most recent file within a directory structure?
91} How do I get command-line reference help?
92} How do I play a sound or a tune from the command line?
93} How do I check if my script was given a parameter?
94} Can I send the script's output both to the screen and a log file?
95} How to perform an operation on all the filenames listed in a file?
96} Can one use a script to columnize a comma separated values file?
97} I need to remove duplicate entries from the output or a file.
98} How do I equate all zip files with the date of their latest file?
99} How do I "touch" a file to update its last modified datestamp?
100} How can I identify and copy the five latest files from a folder?
101} How to capture Volume Serial Number into an environment variable?
102} How can I extract the individual bits from a decimal byte?
103} How do I exit a loop by pressing a key?
104} How can one remove double quotes from a script variable?
105} How to detect whether or not a folder contains hidden files?
106} How to test whether a variable is a non-negative integer?
107} How to do non-trivial renaming such as IMG*.jpg to IMG_*.jpg?
108} How can I execute a script one line at a time to debug it?
109} How do I open e.g. three separate instances of notepad at one go?
110} Can I use a script to determine if a specific printer exists?
111} How can I detect if a folder is shared or not?
112} Help, an old program fails to run since I have no floppy drive.
113} How do I find all *.TXT files on the C: drive sorted by size?
114} How do I pick a file's lines that are three characters long?
115} How can I decompose the path to be one folder per line?
116} How do I get a list all the *.BAT files which are at path?
117} Is it possible to get the physical memory from the cmd?
118} How to handle irregular empty fields of a CSV file?
119} How can I remove any leading zeros from an unsigned integer?
120} How do I use AND/OR/XOR/NOT operators in an IF statement?
121} How do I make a simple reminder to pop up on the desktop?
122} How to list files present in folder A but not in folder B?
123} How to test if a file is in a folder or below two or more times?
124} How do I find files which do NOT contain the search string?
125} How do I get the age of a file? Or of the files in a folder?
126} How do I grep for a line with a tab?
127} How can I pad leading zeros or like to a variable?
128} How to prevent SET /P input from entering the command history?
129} Is it possible to stop and reset the print spooler with a script?
130} How do I find and delete files which contain a specific text?
131} How to get the language of Windows XP in a script ?
132} How to find out the next weekday given today's?
133} How do I get the current IP address, number and name?
134} How do I advance the dates of my certain JPG files by one year?
135} How do I get information about a file extension association?
136} How do I find out when my PC was last booted?
137} I need to resize a group of images from the command line.
138} How can I get the long name of a short-named file or folder?
139} How do I convert UNIX newlines to PC eolns? And vice versa?
140} How do I count how many times a word appears in my text file?
141} Why isn't the ! character always echoed as expected?
142} How to extract the filename from the end of an URL reference?
143} How do I get the current time zone in a script?
144} How do I parse the items from a path like C:\a\b\c\d ?
145} How to find out if WinXP SP2 is installed via a script?
146} Using delayed expansion for giving variable values as arguments
147} What was the time 100 minutes ago?
148} How to calculate the day-of-year number with a pure cmd script?
149} How to calculate a date's week number with a pure cmd script?
150} How can I extract the http and ftp URL:s from an HTML file?
151} Extract the lines of a text file from between to marker-lines?
152} How can I remove all !:s and &:s from a text file with a script?
153} How do I test if my Internet connection to an IP is working?
154} How do I remove leading zeros from a string with script only?
155} How can I use command-line to open a Windows Explorer Window?
156} How does one create a shortcut using the command-line?
157} How to get the count of words and the last word of a variable?
158} Why won't the statements within my if condition work properly?
159} How do I test that a name does not contain lowercase letters?
160} How do I get a list of all my folders with and sorted by size?
161} How do I test that the Windows Script Host is available?
162} Finding duplicate files in a directory tree.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:01 2008
Subject: 1) How get today's date elements into environment variables?
Date: Thu,  6 Mar 2008 01:00:01
From: ts@uwasa.fi (Timo Salmi)

The easiest and most portable solution across different country
configurations is to call DATET.CMD which comes as a part the FAQ
package tscmd.zip. But on to the actual FAQ:

Method 1a:
  @echo off & setlocal enableextensions
  ::
  :: The date presentation assumes DD.MM.YYYY (else customize)
  :: mode con: codepage select=850
  ::
  for /f "tokens=1-3 delims=./-" %%f in ("%date%") do (
    set today_=%%h%%g%%f
    set dd_=%%f
    set mm_=%%g
    set yyyy_=%%h)
  echo %today_%
  echo dd_=%dd_% mm_=%mm_% yyyy_=%yyyy_%
  ::
  :: Clean up for the next test (superfluous because of endlocal)
  for %%v in (today_ dd_ mm_ yyyy_) do set %%v=
  endlocal & goto :EOF
The output could be e.g.
  D:\TEST>cmdfaq
  20040316
  dd_=16 mm_=03 yyyy_=2004

Method 1b: A slight variation of Method 1a. Kok Yong Lee posed the
following question in microsoft.public.win2000.cmdprompt.admin

"I was trying to setup a routine backup of my data with the day of
backup as the name of file. For example
 wzzip 24_03_2006.zip Z:\data\*.*
Currently DATE /t on my machine return "24/03/2006"
I been messing about with the ideas of using the | in order to
retrieve the results from "DATE /t" and then feed it to wzzip as
input by to avail. Any one care to shed some light on this?"

I'll give the custom code. Assume that DATE /T gives 24.03.2006
The outcome can differ between locales. But if the format is that
(or 23/03/2006) then
  @echo off & setlocal enableextensions
  :: Get the date elements
  for /f "tokens=1-3 delims=./-" %%f in ('date /t') do (
    set today_=%%h%%g%%f
    set dd_=%%f
    set mm_=%%g
    set yyyy_=%%h)
  ::
  :: Remove the potential trailing space from the year
  set yyyy_=%yyyy_:~0,4%
  ::
  :: An extra precaution which may be unnecessary
  :: See to it that days 1-9 will always have a leading zero
  set dd_=0%dd_%
  set dd_=%dd_:~-2%
  ::
  :: When you are sure, remove the echo precaution
  echo wzzip %dd_%_%mm_%_%yyyy_%.zip Z:\data\*.*
  endlocal & goto :EOF
Testing this script one will get
  C:\_D\BAS>cmdfaq
  wzzip 24_03_2006.zip Z:\data\*.*

Method 2:
  @echo off & setlocal enableextensions
  mode con: cp select=850>nul
  set dd_=%date:~0,2%
  set mm_=%date:~3,2%
  set yyyy_=%date:~6,4%
  echo dd_=%dd_% mm_=%mm_% yyyy_=%yyyy_%
  endlocal & goto :EOF
The output might be e.g.
  D:\TEST>cmdfaq
  dd_=16 mm_=11 yyyy_=2003
However, in this option one assumes that the day and the month
always are two digits long, i.e. a leading zero is present when
necessary. (For more on this see the code of method 1b and the
similar item #16 about the time.) At the same time note the
substring denotation syntax. It is %var_:~Start,Count% where the
Start commences at 0, not the perhaps more customary 1. I.e. the
index of the first character is 0.

Method 3:
  @echo off & setlocal enableextensions
  for /f "tokens=5-8 delims=.-/ " %%a in (
    'echo.^|date^|find "current"') do (
    set dd_=%%a
    set mm_=%%b
    set yyyy_=%%c
    )
  echo dd_=%dd_% mm_=%mm_% yyyy_=%yyyy_%
  ::
  for /f "tokens=5-8 delims=.-/: " %%a in (
    'echo.^|time^|find "current"') do (
    set hh_=%%a
    set mn_=%%b
    set ss_=%%c
    )
  echo hh_=%hh_% mn_=%mn_% ss_=%ss_%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  dd_=11 mm_=10 yyyy_=2006
  hh_=23 mn_=07 ss_=09

Method 4:
@echo off & setlocal enableextensions
  rem Assuming locale dependent date format DD.MM.YYYY
  rem                   24-hour time format  H:MN:SS
  rem Else customize
  set yyyy_=%date:~6,4%
  set   mm_=%date:~3,2%
  set   dd_=%date:~0,2%
  set   mn_=%time:~3,2%
  set   hh_=%time:~0,2%
  set   hh_=0%hh_: =%
  set   hh_=%hh_:~-2%
  echo %yyyy_%%mm_%%dd_%%hh_%%mn_%
endlocal & goto :EOF

The problem can also be solved with a Visual Basic Script (VBScript)
aided command line script. It is much more complicated, but it has
the advantage of being more stable, i.e. less region dependent than
the pure CMD.EXE solutions. With addition to the date elements also
the time elements are included for demonstration.
  @echo off & setlocal enableextensions
  ::
  :: Make a temporary folder
  if not exist c:\mytemp mkdir c:\mytemp
  ::
  :: Build a Visual Basic Script
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs
  ::
  :: Call the command line script the script host built
  call c:\mytemp\tmp$$$.cmd
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do (
    if exist %%f del %%f)
  rmdir c:\mytemp
  ::
  :: Show the results
  echo Date by %%date%% %date%
  echo Time by %%time%% %time%
  echo dd_=%dd_%
  echo mm_=%mm_%
  echo yyyy_=%yyyy_%
  echo hh_=%hh_%
  echo mi_=%mi_%
  echo ss_=%ss_%
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  Const ForReading = 1, ForWriting = 2, ForAppending = 8             'VBS
  Dim DateNow, TimeNow, fso, f                                       'VBS
  DateNow = Date                                                     'VBS
  TimeNow = Time                                                     'VBS
  Set fso = CreateObject("Scripting.FileSystemObject")               'VBS
  Set f = fso.OpenTextFile("c:\mytemp\tmp$$$.cmd", ForWriting, True) 'VBS
  f.WriteLine "@set dd_=" & Right(0 & DatePart("d", DateNow), 2)     'VBS
  f.WriteLine "@set mm_=" & Right(0 & DatePart("m", DateNow), 2)     'VBS
  f.WriteLine "@set yyyy_=" & DatePart("yyyy", DateNow)              'VBS
  f.WriteLine "@set hh_=" & Right(0 & DatePart("h", TimeNow), 2)     'VBS
  f.WriteLine "@set mi_=" & Right(0 & DatePart("n", TimeNow), 2)     'VBS
  f.WriteLine "@set ss_=" & Right(0 & DatePart("s", TimeNow), 2)     'VBS
  f.Close                                                            'VBS
And example of the output
  D:\TEST>cmdfaq
  Date by %date% 16.03.2004
  Time by %time%  8:27:15.47
  dd_=16
  mm_=03
  yyyy_=2004
  hh_=08
  mi_=27
  ss_=15
In the above for & "Whenever an expression is not a string, it is
converted to a String subtype". So we could as well have
Right("0" & DatePart("d", DateNow), 2)

A more concise presentation
  @echo off & setlocal enableextensions
  set vbs_=%temp%\tmp.vbs
  echo FixedNow=Now>"%vbs_%"
  echo WScript.Echo Right(0 ^& Day(FixedNow), 2) ^&" "^& ^
                    Right(0 ^& Month(FixedNow), 2) ^&" "^& ^
                    Year(FixedNow) ^&" "^& ^
                    Right(0 ^& Hour(FixedNow), 2) ^&" "^& ^
                    Right(0 ^& Minute(FixedNow), 2) ^&" "^& ^
                    Right(0 ^& Second(FixedNow), 2) >> "%vbs_%"
  cscript //nologo "%vbs_%"
  for %%f in ("%vbs_%") do if exist %%f del %%f
  endlocal & goto :EOF
The output might be e.g.
  C:\_D\TEST>cmdfaq
  22 10 2006 12 57 26

>Q: Ok, fine and dandy. But how do I get the day of the week into an
environment variable?

This can be solved e.g. with G(nu)AWK as follows
  @echo
  for /f %%d in ('gawk "BEGIN{printf\"%%s\n\",strftime(\"%%A\")}"') do (
    set wd_=%%d)
  echo %wd_%
The output might be e.g.
  Sunday

>Q: Ok, but how about the number of the week?

It is up to seeing a G(nu)AWK documentation. In this case the
formatting argument is "V" instead of the "A". For better backwards
compatibility, let's use an alternative trick for putting the
value into the environment variable.
  gawk 'BEGIN{printf"@set wk_=%%s\n",strftime("%%V")}'>"%temp%\tmp$$$.bat"
  for %%c in (call del) do %%c "%temp%\tmp$$$.bat"
  echo The week number is = %wk_%
  set wk_=
Note that there a different week number options and standards. See
item #70.

>Q: Ok, but how about the number of the day (1-366)?
Using VBScript
  @echo off & setlocal enableextensions
  :: Make a temporary folder
  if not exist c:\mytemp mkdir c:\mytemp
  :: Build a Visual Basic Script
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs
  :: Call the command line script the script host built
  call c:\mytemp\tmp$$$.cmd
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do if exist %%f del %%f
  rmdir c:\mytemp
  :: Show the result
  echo Day Number dn_=%dn_%
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  Const ForReading = 1, ForWriting = 2, ForAppending = 8              'VBS
  Dim DateNow, fso, f                                                 'VBS
  DateNow = Date                                                      'VBS
  Set fso = CreateObject("Scripting.FileSystemObject")                'VBS
  Set f = fso.OpenTextFile("c:\mytemp\tmp$$$.cmd", ForWriting, True)  'VBS
  f.Write "@set dn_=" & DatePart("y", DateNow)                        'VBS
  f.Close                                                             'VBS

Alternatively, much more concisely
  @echo off & setlocal enableextensions
  if not exist c:\mytemp mkdir c:\mytemp
  echo>c:\mytemp\tmp$$$.vbs WScript.Echo DatePart("y", Date)
  for /f %%n in ('cscript //nologo c:\mytemp\tmp$$$.vbs') do set dn_=%%n
  for %%f in (c:\mytemp\tmp$$$.vbs) do if exist %%f del %%f
  rmdir c:\mytemp
  echo Day Number dn_=%dn_%
  endlocal & goto :EOF

An output example:
  C:\_D\TEST>echo %date%
  23.05.2006
  C:\_D\TEST>cmdfaq
  Day Number dn_=143

Consider an application needing today's date. Say we wish to find
all the files made today in a folder:
  @echo off & setlocal enableextensions enabledelayedexpansion
  for %%f in ("c:\mytest\*.*") do (
    echo "%%~tf" | find "%date%" > nul
    if !errorlevel! EQU 0 echo %%~tf %%~zf "%%~ff"
    )
  endlocal & goto :EOF
The output could be e.g.
  C:\MYTEST>cmdfaq
  23.05.2006 06:51 216 "C:\MYTEST\CMDFAQ.CMD"

Incidentally, for demonstration, that can be written with an
alternative syntax, not needing the enabledelayedexpansion
  @echo off & setlocal enableextensions
  for %%f in ("d:\bas\*.*") do (
    echo "%%~tf" | find "%date%" > nul && echo %%~tf %%~zf "%%~ff"
    )
  endlocal & goto :EOF
or, finding the files NOT made today
  @echo off & setlocal enableextensions
  for %%f in ("c:\mytest\*.*") do (
    echo "%%~tf" | find "%date%" > nul || echo %%~tf %%~zf "%%~ff"
    )
  endlocal & goto :EOF
For more on the conditional processing symbol || see
 hh ntcmds.chm::/ntcmds_shelloverview.htm

Back to getting the date and time. An advanced script method. Note,
however, that the WMIC (Windows Management Instrumentation
Command-Line Utility) is only available since XP.
  @echo off & setlocal enableextensions
  for /f "tokens=* skip=1" %%i in ('wmic OS Get LocalDateTime') do (
    set LocalDateTime=%%i)
  echo LocalDateTime: %LocalDateTime%
  ::
  set year_=%LocalDateTime:~0,4%
  set month_=%LocalDateTime:~4,2%
  set day_=%LocalDateTime:~6,2%
  set hour_=%LocalDateTime:~8,2%
  set minute_=%LocalDateTime:~10,2%
  set second_=%LocalDateTime:~12,2%
  set sec100_=%LocalDateTime:~15,3%
  set tz_=%LocalDateTime:~21,5%
  set tz_=%tz_: =%
  ::
  echo year_    %year_%
  echo month_   %month_%
  echo day_     %day_%
  echo hour_    %hour_%
  echo minute_  %minute_%
  echo second_  %second_%
  echo sec100_  %sec100_%
  echo tz_      %tz_%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  LocalDateTime: 20060806213955.468000+180
  year_    2006
  month_   08
  day_     06
  hour_    21
  minute_  39
  second_  55
  sec100_  468
  tz_      +180.

A reasonably locale-independent date elements' extraction with XP
cmd.exe with no third-party utilities involved:
  @echo off & setlocal enableextensions
  ::
  :: Still debugging?
  set debug=true
  ::
  :: Get the date from the first line of the date command
  for /f "tokens=2,5 delims= " %%a in ('echo.^|date') do (
    if not defined date_ set lang_=%%a
    if not defined date_ set date_=%%b
    )
  if defined debug echo %lang_%
  if defined debug echo %date_%
  ::
  :: Get the date format from the first line of the date command
  for /f "tokens=5 delims= " %%a in ('echo.^|date') do (
    set dateform_=%%a
    )
  if defined debug echo %dateform_%
  ::
  :: Local, but not that local that it is not English
  if not "%lang_%"=="current" (
    echo Error: The OS is not in English
    goto :EOF
    )
  ::
  :: Get the order of the date information
  set field1=%dateform_:~1,2%
  set field2=%dateform_:~4,2%
  set field3=%dateform_:~7,2%
  if defined debug echo %field1% %field2% %field3%
  if defined debug echo.
  ::
  :: Test and set according to the date format order
  :: dd-mm-yy
  if "%field1%"=="dd" (
    set day_=%date_:~0,2%
    if "%field2%"=="mm" (
      set month_=%date_:~3,2%
      set year_=%date_:~6,4%
      )
    )
  :: mm-dd-yy
  if "%field1%"=="mm" (
    set month_=%date_:~0,2%
    if "%field2%"=="dd" (
      set day_=%date_:~3,2%
      set year_=%date_:~6,4%
      )
    )
  :: yy-mm-dd
  if "%field1%"=="yy" (
    set year_=%date_:~0,4%
    if "%field2%"=="mm" (
      set month_=%date_:~5,2%
      set day_=%date_:~8,2%
      )
    )
  :: yy-dd-mm
  if "%field1%"=="yy" (
    set year_=%date_:~0,4%
    if "%field2%"=="dd" (
      set day_=%date_:~5,2%
      set month_=%date_:~8,2%
      )
    )
  ::
  :: Display the result
  if not defined day_ (
    echo Error: Unidentified date format
    goto :EOF
    )
  echo day_=%day_%
  echo month_=%month_%
  echo year_=%year_%
  endlocal & goto :EOF

The output might be e.g.
C:\_D\TEST>cmdfaq
  29.01.2007
  (dd-mm-yy)
  dd mm yy
  day_=29
  month_=01
  year_=2007

References/Comments:
 http://www.google.com/groups?selm=c22iq3%241dm%2403%241%40news.t-online.com
 http://www.google.com/groups?selm=k9bxa7zebut0.y9wmsipnutlp.dlg%4040tude.net
 http://www.google.com/groups?selm=ehdse8%242mr6%241%40news.mtu.ru
 http://support.microsoft.com/kb/290216/en-us
 http://support.microsoft.com/kb/555314/en-us
 http://www.google.com/groups?selm=epl874%242pur%241%40news.rtcomm.ru
 http://www.google.com/groups?selm=e9str2d7avc8foib2pkpcmlqi6835qkpt6%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:02 2008
Subject: 2) On Windows XP how do you stop the script files from closing?
Date: Thu,  6 Mar 2008 01:00:02
From: ts@uwasa.fi (Timo Salmi)

If one runs a .cmd script file by clicking the icon of the script,
the window will close after the processing is completed.
Occasionally this may not be what the user wants.

Method 1: To keep the window open to see the results one can use:
  :: The body of the script with whatever task.
  :: Then
  pause
This will produce
  Press any key to continue . . .
The window will then close when a key is pressed.

You also might notice that some of my scripts included in this
collection have the concluding line
  if not defined cmdbox if defined PauseIfFromDesktop pause
The purpose of such a line is to prevent a script from immediately
closing on completion if called (clicked) from the desktop. This
allows you to view the results. However, this requires some special
arrangements.
 a) I have defined a PauseIfFromDesktop variable into my
    default environment:
      Right click: My Computer
      Choose Properties
      Choose Advanced
      Click "Environment Variables"
      For User variables click New
      Define PauseIfFromDesktop true
 b) See the "set cmdbox=true" spot in the next item.

Method 2: There is a more generic solution. Put as the very last
line of your script
  cmd
The window will remain open as is familiar from the Win3.x/95/98/Me
dosbox, and it will allow you to give further commands. To finally
close the window, type "exit". See the next item for utilizing the
"cmd" line in customizing a command line window to your liking.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:03 2008
Subject: 3) How can I customize the Command Prompt Window with script commands?
Date: Thu,  6 Mar 2008 01:00:03
From: ts@uwasa.fi (Timo Salmi)

In fact the "cmd" method in the previous solution is the basis for
an answer to a similar question "How can I customize the Command
Prompt window with script commands?". The answer is that you first
give all the commands you want, then conclude with "cmd". And
naturally prepare a desktop icon to point to your script so that you
can open the window you have customized. Below is one example.

  @echo off
  echo +----------------------------------------+
  echo ^| CMDBOX.CMD CLI box by Prof. Timo Salmi ^|
  echo ^| Last updated Sat 15-November-2003      ^|
  echo +----------------------------------------+
  echo.
  ::
  :: Check about the Windows version
  if [%OS%]==[Windows_NT] goto _doit
  echo This script is for Windows NT/2000/XP only.
  echo Or have you tampered with the predefined variables?
  pause
  goto _out
  ::
  :_doit
  :: Augment the Windows path (customize as appropriate) and show
  path c:\mytools;%path%
  path
  ::
  :: Select the fastest keyboard repeat-rate,
  mode con: rate=32 delay=1
  ::
  :: Select the code page Multilingual Latin 1
  mode con: codepage select=850
  ::
  :: Choose (e.g.) blue background and bright white foreground
  color 1F
  ::
  :: Make a home folder and go there
  if not exist c:\_h mkdir c:\_h
  c:
  cd c:\_h
  echo cd c:\_h
  ::
  :: Tag that we are in the Command Prompt Windows so that,
  :: if need be, scripts can be made aware if they are being
  :: called in the window instead a direct call from an icon
  set cmdbox=true
  ::
  :: Finally, start "a new instance of the command interpreter"
  cmd
  ::
  :: The exit in case something went wrong
  :_out

A script like this would display something like the following

  PATH=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;...

  Status for device CON:
  ----------------------
      Lines:          1000
      Columns:        80
      Keyboard rate:  31
      Keyboard delay: 1
      Code page:      850

  Microsoft Windows XP [Version 5.1.2600]
  (C) Copyright 1985-2001 Microsoft Corp.

C:\_H>

If you just want to skip all that output, redirect to nul. For
example
  mode con: codepage select=850 >nul

To suppress the "Microsoft Windows" announcement, add switch /k to
the command interpreter calling line:
  cmd /k
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:04 2008
Subject: 4) How can I test is it on MSDOS/Win3..9x/Me or NT/2000/XP?
Date: Thu,  6 Mar 2008 01:00:04
From: ts@uwasa.fi (Timo Salmi)

This is how to test it:
  @echo off
  set is_nt=false
  echo.>nul & set is_nt=true
  :: Show the result
  echo is_nt=%is_nt%
It is based on the fact that in NT/2000/XP CMD.EXE "&" can be used
to separate multiple commands on one command line while in
MSDOS/Win3..9x/Me COMMAND.COM the "&" is not recognized.

Another, very similar option is based on the maximum length of a
label in the various systems:
  @echo off
  ::
  goto _123456789
  :_1234567
  set is_nt=false
  goto _tell
  :_123456789
  set is_nt=true
  goto _tell
  ::
  :_tell
  echo is_nt=%is_nt%
The output on an XP would be
  C:\_D\TEST>cmdfaq
  is_nt=true

A third option is the following. It assumes that you have not
tampered with the predefined system environment variables for
Windows XP. Their values can be changed by the user, even if it is
highly unrecommended.
  @echo off
  if [%OS%]==[Windows_NT] goto _xp
  :: whatever MSDOS..95/98/ME-syntax commands
  goto _end
  :_xp
  :: whatever NT/2000/XP-syntax commands
  :_end

A more specific alternative testing for XP in particular is the
following
  @echo off
  set is_xp=false
  ver|find "Microsoft Windows XP"
  if %errorlevel% EQU 0 set is_xp=true
  echo is_xp=%is_xp%
  set is_xp=
The output on an XP could be e.g.
  C:\_D\TEST>cmdfaq
  Microsoft Windows XP [Version 5.1.2600]
  is_xp=true
The solution has the added advantage that one can build a more
comprehensive identification on this alternative if one first maps
what the various Windows or MS-DOS versions will return for VER.

For a different, comprehensive identification of the particular
Windows_NT category, search http://www.commandline.co.uk/lib/treeview/index.php
by Ritchie Lawrence for the GetOS function.

James Pang wrote:
> I want to use below command to set the output string of find into
>  variable 'v' ver | find "Windows" | set /p v=
> but it doesn't work!!! anybody has any idea?

My response: That is a problem that is a superficially easy
  @echo off & setlocal enableextensions
  if [%OS%]==[Windows_NT] echo NT/2000/XP...
  for /f "tokens=2 delims=[]" %%v in ('ver') do set ver_=%%v
  echo %ver_%
  endlocal & goto :EOF
Which would give e.g.
  C:\_D\BAS>cmdfaq
  NT/2000/XP...
  Version 5.1.2600

However, that is somewhat of a circular deduction. We already have
advance knowledge what the OS is when using the above! Note that
'ver' output fields can differ between Windows versions. The more
fundamental question is how does one generally find out in a script
which OS? That problem has been tackled by Ritchie Lawrence in
 http://www.commandline.co.uk/lib/Batch%20Function%20Library/System%20Functions/GetOS.html

Here is my rendition, partly incomplete and (naturally) not tested
for all the OSes.
  @echo off
  set my_os=
  ::
  echo Test|find "Fail">nul
  if errorlevel 0 if not errorlevel 1 set my_os=Pre MS-DOS 6.0
  if not "%my_os%"=="" goto _show
  ::
  ver|find "6.22">nul
  if errorlevel 0 if not errorlevel 1 set my_os=MS-DOS 6.22
  ::
  ver|find "Windows 95.">nul
  if errorlevel 0 if not errorlevel 1 set my_os=Windows95
  ::
  if not "%OS%"=="Windows_NT" goto _show
  ::
  net config workstation|find /i "Software version"|find "NT40">nul
  if errorlevel 0 if not errorlevel 1 set my_os=Windows NT 4.0
  ::
  net config workstation|find /i "Software version"|find "2000">nul
  if errorlevel 0 if not errorlevel 1 set my_os=Windows 2000
  ::
  net config workstation|find /i "Software version"|find "2002">nul
  if errorlevel 0 if not errorlevel 1 set my_os=Windows XP
  ::
  net config workstation|find /i "Software version"|find "2003">nul
  if errorlevel 0 if not errorlevel 1 set my_os=Windows 2003
  ::
  :_show
  if "%my_os%"=="" set my_os=Unknown
  echo %my_os%
  for %%v in (my_os) do set %%v=
The output could be e.g.
  C:\_D\TEST>cmdfaq
  Windows XP

Another option:
  @echo off & setlocal enableextensions
  set xp_=
  systeminfo|find "Microsoft Windows XP">nul
  if %errorlevel% EQU 0 set xp_=true
  if defined xp_ (
    echo XP
    ) else (
    echo Not XP)
  endlocal & goto :EOF

Or
  @echo off & setlocal enableextensions
  ::
  :: Get the Operating System
  for /f "tokens=2,*" %%i in (
  'reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName^
    ^| find "REG_SZ"') do set prod_=%%j
  echo.%prod_%|find "Microsoft Windows XP">nul
  if %errorlevel% EQU 0 set xp_=true
  if defined xp_ (
    echo XP
    ) else (
    echo Not XP)
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:05 2008
Subject: 5) How do I get a fully qualified path name of my script?
Date: Thu,  6 Mar 2008 01:00:05
From: ts@uwasa.fi (Timo Salmi)

At the command prompt enter "FOR /?". There look for the information
on the substitution of FOR variable references. In this particular
case you would use the "%~fI". Utilize the fact that the unexpanded
name of the script called will be in the parameter %0. Let's test it
  @echo off
  set fullnam_=%~f0
  echo %fullnam_%
  set fullnam_=
The output could be e.g.
  C:\_D\TEST>cmdfaq
  C:\_D\TEST\CMDFAQ.CMD
Note that the name might contain spaces after the expansion even
when the plain filename might not. So you may need to enclose
"fullnam_" into quotes, if you use it.

Another demonstration of the expansion is
  @echo off
  for %%f in (*.*) do echo %%~ff
It includes the full path into the "bare" default folder list.
The output might be something like this:

  C:\MYSCRIPT\XTOOLS\CMDBOX.CMD
  C:\MYSCRIPT\XTOOLS\FORFILES.EXE
  C:\MYSCRIPT\XTOOLS\HOMMAG.CMD
  C:\MYSCRIPT\XTOOLS\TEST.CMD
  C:\MYSCRIPT\XTOOLS\XPNEW.CMD
  C:\MYSCRIPT\XTOOLS\XPNEW1.CMD
  C:\MYSCRIPT\XTOOLS\XPTD.CMD
  C:\MYSCRIPT\XTOOLS\XPTDSUB.CMD
  C:\MYSCRIPT\XTOOLS\XPTODAY.CMD
  C:\MYSCRIPT\XTOOLS\XUNSUBST.CMD

References/Comments:
 http://www.google.com/groups?selm=uaiog0tc9rgjfus35i4um08bpjus3q7s9m%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:06 2008
Subject: 6) How does one get yesterday's date?
Date: Thu,  6 Mar 2008 01:00:06
From: ts@uwasa.fi (Timo Salmi)

Utilizing G(nu)Awk we can demonstrate
  @echo off & setlocal enableextensions
  gawk 'BEGIN{printf"%%s\n",strftime("%%x",systime()-24*60*60)}'
  set back_=1
  gawk 'BEGIN{printf"@set datewas_=%%s\n",^
    strftime("%%d.%%m.%%Y",systime()-%back_%*24*60*60)}'^
    >>"%TEMP%\tmp$$$.cmd"
  for %%f in (call del) do %%f "%TEMP%\tmp$$$.cmd"
  echo The date was %datewas_%
  endlocal & goto :EOF

The output will be something like
  Wed Nov 19 2003
  The date was 19.11.2003

As a sideissue also notice continuing a line with the caret ^.

There is a catch. If one uses a different gawk, say from
 878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip
 UnxUpdates.zip Updates for UnxUtils GNU utilities for native Win32
then with that gawk port (let's call it unxgawk) one has to adjust
the syntax to
  @echo off & setlocal enableextensions
  unxgawk "BEGIN{printf\"%%s\n\",strftime(\"%%x\",systime()-24*60*60)}"
  set back_=1
  unxgawk "BEGIN{printf\"@set datewas_=%%s\n\",strftime(\"%%d.%%m.%%Y\",systime()-%back_%*24*60*60)}">>"%TEMP%\tmp$$$.cmd"
  for %%f in (call del) do %%f "%TEMP%\tmp$$$.cmd"
  echo The date was %datewas_%
  endlocal & goto :EOF

This task could also be performed using Zeller's congruence. It will
take some programming. External date to/from Julian date number
programs are utilized in the solution below
  @echo off
  ::
  :: Get and show today's Julian date number
  :: Requires DATE2NUM.EXE from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
  DATE2NUM /set > "%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  echo datenum_=%datenum_%
  ::
  :: Calculate yesterday's Julian date number
  set /a yesterday_=%datenum_% -1
  ::
  :: Convert it back into a date
  :: Requires NUM2DATE.EXE from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
  NUM2DATE %yesterday_% /set > "%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  echo dd_=%dd_% mm_=%mm_% yyyy_=%yyyy_%
  ::
  :: Clean up
  for %%v in (datenum_ yesterday_ dd_ mm_ yyyy_) do set %%v=
The output would be something like
  D:\TEST>cmdfaq
  datenum_=2452982
  dd_=7 mm_=12 yyyy_=2003

Yesterday date problem can also be solved with a Visual Basic Script
(VBScript) aided command line script
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo tmp$$$.vbs
  :: Call the command line script the script host built
  call tmp$$$.cmd
  :: Clean up
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  :: Show the result
  echo %date%
  echo yd_=%yd_%
  endlocal & goto :EOF
  '
  Dim oShell                                                                  'VBS
  Set oShell = WScript.CreateObject ("WSCript.shell")                         'VBS
  oShell.run "cmd /c echo @set yd_=" & DateAdd("d",-1,Date) & " > tmp$$$.cmd" 'VBS

The output would be something like
  D:\TEST>cmdfaq
  31.01.2004
  yd_=30.01.2004

Also see item #31. Also related the accompanying EDATE.CMD script.

References/Comments:
 http://www.google.com/groups?selm=4HHCtPLs78GAFwt8%40merlyn.demon.co.uk
 http://groups.google.com/group/alt.msdos.batch.nt/browse_frm/thread/569e6991b4af325e/4595b370fb03dc1f?hl=en&lr=&ie=UTF-8&rnum=1&prev=/groups%3Fselm%3Db2a353ab.0407051330.6d17beb9%40posting.google.com#4595b370fb03dc1f
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:07 2008
Subject: 7) How can I test if two files agree in size and datetime stamp?
Date: Thu,  6 Mar 2008 01:00:07
From: ts@uwasa.fi (Timo Salmi)

This one is rather simple given the features of XP CMD.EXE.
  @echo off
  ::
  setlocal
  :: Get the filenames (one way or the other)
  set file1_=%1
  set file2_=%2
  set file1_=c:\_d\bas\batfaq2.bat
  set file2_=c:\_f\xtools\xptd.cmd
  ::
  :: Get the filesizes and the datestamps
  for %%f in (%file1_%) do set size1_=%%~zf
  for %%f in (%file2_%) do set size2_=%%~zf
  for %%f in (%file1_%) do set date1_=%%~tf
  for %%f in (%file2_%) do set date2_=%%~tf
  ::
  :: Demonstrate what we've got so far
  echo %date1_% %file1_% %size1_%
  echo %date2_% %file2_% %size2_%
  ::
  :: Do the comparison
  set same_=false
  if "%size1_%"=="%size2_%" if "%date1_%"=="%date2_%" set same_=true
  ::
  :: Display the resuls
  if /i "%same_%"=="true" (
    echo The file dates and sizes agree
    ) else (
    echo The file dates and/or sizes do not agree)
  endlocal
  goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:08 2008
Subject: 8) How do I find all the files made at of after YYYYMMDD HHMM?
Date: Thu,  6 Mar 2008 01:00:08
From: ts@uwasa.fi (Timo Salmi)

Let us start with the easier task of copying all the files made
today.
  @echo off & setlocal enableextensions
  :: The date presentation assumes DD.MM.YYYY (else customize)
  for /f "tokens=1-3 delims=./-" %%a in ("%date%") do (
    set dd_=%%a
    set mm_=%%b
    set yyyy_=%%c)
  set dd_=0%dd_%
  set dd_=%dd_:~-2%
  set xcdate_=%mm_%-%dd_%-%yyyy_%
  ::
  :: Test the copying. When done, remove the test switch /l
  :: Customize the target s:\
  for /f "delims=" %%d in ('dir "C:\*.*" /s /b /a:d-s-h') do (
    xcopy /l /p /v /f /d:%xcdate_% "%%~fd\*.*" s:\
    )
  endlocal & goto :EOF

Then lets move to the more demanding task of finding the files made
at or after YYYYMMDD HHMM

  @echo off
  ::..................................................................
  ::
  :: AFTER.CMD This is the first of the two script files needed
  ::
  :: Get today's date elements
  mode con: codepage select=850 > nul
  set dd_=%date:~0,2%
  set mm_=%date:~3,2%
  set yyyy_=%date:~6,4%
  ::
  :: Process the user's parameters
  :: Note below the need of the escape character (^) because
  :: parentheses are special characters, too
  if not "%1"=="" goto _set (
    echo.
    echo Usage: %0 YYYYMMDD ^(or "today"^) HHMM
    echo.
    goto :EOF
    )
  :_set
  set cutdate_=%1
  if /i "%cutdate_%"=="today" set cutdate_=%yyyy_%%mm_%%dd_%
  if "%2"=="" (
    set cutime_=0000
    ) ELSE (
    set cutime_=%2)
  ::
  :: Traverse the folder trees
  for /f %%f in ('dir C:\*.* /s /b /-c /a:-d-s-h') do (
    call AFTER1.CMD %%f
    )
  ::
  :: Clean up
  for %%v in (dd_ mm_ yyyy_ cutdate_ cutime_) do set %%v=

  @echo off
  ::..................................................................
  :: This is a separate file, AFTER1.CMD
  :: Alternative a pseudo-subroutine might well be attempted within the
  :: first script file, but that method is left for the other items.
  ::
  :: AFTER1.CMD for AFTER.CMD by Prof. Timo Salmi, University of Vaasa
  :: The auxiliary script for getting the file date and time stamp
  ::
  for %%a in (%1) do set fdate_=%%~ta
  for /f "tokens=1-5 delims=./-: " %%a in ('echo %fdate_%') do (
    set fdd_=%%a
    set fmm_=%%b
    set fyyyy_=%%c
    set fhh_=%%d
    set fmn_=%%e)
  ::
  :: Do the comparison and display
  if %fyyyy_%%fmm_%%fdd_% LSS %cutdate_% goto :EOF
  if %fhh_%%fmn_% LSS %cutime_% goto :EOF
  echo %1 %fdd_%.%fmm_%.%fyyyy_% %fhh_%:%fmn_%
  for %%v in (fdd_ fmm_ fyyyy_ fhh_ fmn_) do set %%v=

The output might look something like this
  C:\CMDTEST>AFTER today 1200
  C:\CHYDE\VIESTI.DOC 23.11.2003 13:28
  C:\CHYDE\VIESTI.TXT 23.11.2003 13:03
  C:\CMD\1CMDFAQ.TXT 23.11.2003 15:13
  C:\PGP\RANDSEED.BIN 23.11.2003 11:31
  C:\XTOOLS\CMDBOX.CMD 23.11.2003 17:38
  C:\XTOOLS\XUNSUBST.CMD 23.11.2003 17:41

It is easy to see that by suitably customizing the last "echo" line
you could perform many kinds of commands on those files. Or you
could first direct the output as a safety to yet another script file
for further inspection and editing.

Another option, requiring just a single script file
  @echo off & setlocal enableextensions enabledelayedexpansion
  echo.
  echo.+-------------------------------------------+
  echo ^| Display files after a given date and time ^|
  echo ^| By Prof. Timo Salmi, University of Vaasa  ^|
  echo ^| XPTODAY Last modified Tue 10-Feb-2004     ^|
  echo +-------------------------------------------+
  echo.
  ::
  rem Some customization will be required
  rem  1) Choose the location of your list file C:\_M\TODAY.DIR
  rem  2) Choose the folders to browse from in the section
  rem     "Browse the folders"
  rem  3) Possibly also the order of the date elements
  ::
  :: The instructions
  if "%1"=="" (
    echo Usage: %~f0 SinceDateAs:YYYYMMDD [SinceTimeAs:HHMN]
    echo.
    echo For example: %~f0 20031116 0900
    echo              %~f0 today 0900
    echo              %~f0 today [the time defaults to 00:00]
    echo.
    echo Careful, no error checking!
    goto :EOF
  )
  ::
  echo This might take some time.
  set /p ask_="Run anyway [Y/n]?"
  if /i "%ask_%"=="n" goto :EOF
  set ask_=
  ::
  echo.
  echo Working, patience please...
  ::
  :: Delete the old list file
  for %%f in (C:\_M\TODAY.DIR) do if exist %%f del %%f
  ::
  :: Get today's date elements
  mode con: codepage select=850 > nul
  set dd_=%date:~0,2%
  set mm_=%date:~3,2%
  set yyyy_=%date:~6,4%
  ::
  :: Process the user's parameters
  set cutdate_=%1
  if /i "%cutdate_%"=="today" set cutdate_=%yyyy_%%mm_%%dd_%
  if "%2"=="" (
    set cutime_=0000
    ) ELSE (
    set cutime_=%2)
  ::
  :: Browse the target folders
  for /f "tokens=* delims=" %%f in (
   'dir C:\_D\*.*
        C:\_E\*.*
        C:\_F\*.*
        C:\_G\*.*
        C:\_H\*.*
        C:\_L\*.*
   /s/b/a:-d-h-s'
    ) do (
    set fdate_=%%~tf
    set frevdate_=!fdate_:~6,4!!fdate_:~3,2!!fdate_:~0,2!
    set ftime_=!fdate_:~11,2!!fdate_:~14,2!
    set fattr_=%%~af
    set fsize_=         %%~zf
    set fsize_=!fsize_:~-10!
    if !frevdate_! EQU %cutdate_% (
      if !ftime_! GEQ %cutime_% (
        echo !frevdate_! !ftime_! !fattr_! !fsize_! %%~ff >> C:\_M\TODAY.DIR
        )
      )
    )
  ::
  :: Display the results
  echo.
  type C:\_M\TODAY.DIR | sort | more
  ::
  :: Delete the results file if you so wish
  del /p C:\_M\TODAY.DIR
  ::
  endlocal & goto :EOF

Also see RECENT.CMD and RECENT.VBS scripts included in this FAQ
package.

References/Comments:
 http://www.google.com/groups?selm=c0b8pd%24nbr%2406%241%40news.t-online.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:09 2008
Subject: 9) How can I suppress script error messages altogether?
Date: Thu,  6 Mar 2008 01:00:09
From: ts@uwasa.fi (Timo Salmi)

This is a classic carryover from UNIX. First consider
  @echo off
  echo Customized pause, press the anykey ...
  pause>nul
The usual pause message goes to the nul bitbucket, and only the
customized message appears (actually before the pause).

When you type
  dir *.tex > texlist.dir
you'll get the folder listing into texlist.dir but if there are
any errors, then they are forced on the standard output device (the
screen), not to textlist.dir. You would have on the screen the
message
  File Not Found

What if you do not wish to see that message, but redirect it to the
bit bucket. This is the syntax then
  @echo off
  dir *.tex > texlist.dir 2>&1
Since the test folder has no *.tex file, a file "File Not Found"
message is produced, but it is redirected to texlist.dir, not to the
screen.

Consider the following cryptic-looking script
  @echo off
  dir > nul 2>&1
It produces no output. Now why would one wish to do something like
that? ... Because, some commands return an errorlevel, and that is
what one really is after.

For example XCOPY returns exit codes as shown by the demonstration
below where "Y:" is a non-existent drive in the test.
  @echo off
  xcopy /v *.* Y: > nul
  for %%L in (5 4 3 2 1 0) do if errorlevel==%%L (
    set level_=%%L
    goto _tell
    )
  :_tell
  echo The errorlevel of the operation was %level_%
  set level_=

The output produced will be
  Invalid drive specification
  The errorlevel of the operation was 4
However, change the second line to
  xcopy /v *.* Y: > nul 2>&1
and the only output will be just
  The errorlevel of the operation was 4

Another example. Assume that there is no disk in the A: drive.
  dir a:
will produce
  The device is not ready.
However
  dir a:>nul 2>&1
will only produce a blank line, but not the error message.

Why 2>&1? Because the numeric equivalent of the STDERR is 2 and the
numeric equivalent of STDOUT handle is 1. This becomes more evident
if you do the following in phases
  dir NoSuchFile 2>stderr.tmp
The error message will be directed to stderr.tmp while the rest will
appear on the screen. Then enter
  dir NoSuchFile>out.tmp 2>&1
and all the output, the error message included, will go to out.tmp

This item was about suppressing error messages. Another way of
thinking is avoiding the errors, at least in easily expected
situations. Consider
 DIR C:\_M\*.CMD
which will produce
 File Not Found
if no *.CMD files are located in the folder C:\_M. This can be
avoided by using either
  if exist C:\_M\*.BAS dir C:\_M\*.BAS
or e.g.
  for %%f in (C:\_M\*.BAS) do echo %%~tf %%~zf  %%~ff

Below is a demonstration how to play with stderr. The unraveling and
customizing to one's own potential task is left to the reader
  @echo off & setlocal enableextensions
  for %%f in (stderr.tmp tmp$$$.cmd) do if exist %%f del %%f
  set var_=
  ::
  dir cmdfaq.cmd 2>stderr.tmp
  ::
  for /f "tokens=* delims=" %%r in ('
    type stderr.tmp') do echo @set var_=%%r>tmp$$$.cmd
  if exist tmp$$$.cmd call tmp$$$.cmd
  ::
  if defined var_ (
    echo var_=%var_%
    ) else (
    echo var_ is undefined. The DIR command was successful.
    )
  ::
  for %%f in (stderr.tmp tmp$$$.cmd) do if exist %%f del %%f
  endlocal & goto :EOF

The output (slightly condensed) will be
  C:\_D\TEST>cmdfaq
   Directory of C:\_D\TEST
  var_=File Not Found

Or, if you instead have in the script
   dir MyExisting.txt 2>stderr.tmp
the output (again slightly condensed) will be
  C:\_D\TEST>cmdfaq
   Directory of C:\_D\TEST
  16.04.2006  06:36               523 MyExisting.txt
                 1 File(s)            523 bytes
                 0 Dir(s)  27 814 150 144 bytes free
  var_ is undefined. The DIR command was successful.

References/Comments:
 hh ntcmds.chm::/redirection.htm
 http://www.google.com/groups?selm=1138300141.619659.182690%40z14g2000cwz.googlegroups.com
 http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:10 2008
Subject: 10) How can I change the environment variable values within a FOR loop?
Date: Thu,  6 Mar 2008 01:00:10
From: ts@uwasa.fi (Timo Salmi)

Unless enabledelayedexpansion is on, by default a for loop expands
its environment variables before the execution of the loop. Unlike
in programming with compilers the value of a variable that is
changed within a loop will not be set to its new value until the
loop is exited. (The same goes for any environment variable
expression on multiple lines within parentheses.)

For more information type SET /?

Consider the following, faulty example to count the number of lines in
a file
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  ::
  set lineCount=0
  ::
  for /f "delims=" %%r in ('type myfile.txt') do (
    set /a lineCount+=1
    echo %lineCount% %%r
    )
  echo The number of lines is %lineCount%
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF
The output will obviously not be quite what one would want:
  D:\TEST>cmdfaq
  0 This is the first line
  0 This is the second line
  0 This is the third line
  0 This is the fourth line
  The number of lines is 4

There are two ways to amend. One is to put the operations into a
subroutine outside the loop as follows
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  ::
  set lineCount=0
  ::
  for /f "delims=" %%r in ('type myfile.txt') do (
    call :WriteOneLine %%r
    )
  echo The number of lines is %lineCount%
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF
  ::
  :: =============================================
  :WriteOneLine
  set /a lineCount+=1
  echo %lineCount% %*
  goto :EOF
The output will be
  D:\TEST>cmdfaq
  1 This is the first line
  2 This is the second line
  3 This is the third line
  4 This is the fourth line
  The number of lines is 4

The other option is to enable "delayed expansion"
  @echo off & setlocal enableextensions enabledelayedexpansion
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  ::
  set lineCount=0
  ::
  for /f "delims=" %%r in ('type myfile.txt') do (
    set /a lineCount+=1
    echo !lineCount! %%r
    )
  echo The number of lines is %lineCount%
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF
The value of an environment variable in delayed expansion in the
above is to be indicated by !variable! instead of the more familiar
%variable%. The output will be
  D:\TEST>cmdfaq
  1 This is the first line
  2 This is the second line
  3 This is the third line
  4 This is the fourth line
  The number of lines is 4
Also see item 158.

To conclude, an extra example of a for loop, using this time the
subroutine method
  @echo off
  ::
  :: A true life example of an XP script used in a repetitive task.
  :: It well demonstrates how change the values of environment
  :: variable WITHIN a FOR loop.
  ::
  echo.+-------------------------------------------------------------+
  echo ^| Convert Timo's IBM PC character text mail files into LATIN1 ^|
  echo ^| By Prof. Timo Salmi, Last modified Tue 25-November-2003     ^|
  echo +-------------------------------------------------------------+
  echo.
  ::
  :: Ask for confirmation before we go on, case insensitive
  set /p ask_=Convert, are you sure [y/N]?
  if /i not "%ask_%"=="y" if /i not "%ask_%"=="yes" goto :EOF
  :: It is prudent practice to release the query variable immediately
  :: (even if in this particular script it happens to be the only question)
  set ask_=
  ::
  :: Set the path for the origin and target files
  :: The names of the files is meant to stay the same
  set pathin_=C:\_D\MAIL
  set pathout_=C:\Documents and Settings\ts\mail
  ::
  :: Go trough all the relevant files
  :: and call the pseudo-subroutine for each one
  for %%f in (BATCH.MAI
  NEWS0001.MAI
  SCIWK001.MAI
  TIMO.MAI
  TIMO0001.MAI
  TIMO0002.MAI
  TIMO0003.MAI
  TIMO0004.MAI
  WORK0001.MAI
  WORK0002.MAI) do call :_subru %%f
  ::
  :: Finally clean up (instead of playing around with setlocal and endlocal)
  for %%v in (pathin_ pathout_ filein_ fileout_) do set %%v=
  :: Exit the script
  goto :EOF
  ::
  :: *** The pseudo-subroutine for each loop ***
  ::
  :_subru
  set filein_="%pathin_%\%1"
  set fileout_="%pathout_%\%1"
  ::
  :: Do the actual task
  :: note that this way we can easily have redirection within the loop
  :: IBM2LAT1 is an external (Turbo Pascal 7.01) filter program
  :: But that is beside the point since we could have any task here
  :: (Performs the same task as item #28)
  IBM2LAT1 < %filein_% > %fileout_%
  ::
  :: Show the relevant files at each loop, date/time size fullname
  for /f "tokens=1 delims=" %%f in (%filein_%)  do echo %%~tf %%~zf %%~ff
  for /f "tokens=1 delims=" %%f in (%fileout_%) do echo %%~tf %%~zf %%~ff
  echo.
  goto :EOF

There is, however, an interesting and sometimes useful twist using call.
Consider (note, no delayed expansion needed)
  @echo off & setlocal enableextensions disabledelayedexpansion
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  ::
  set lineCount=0
  ::
  for /f "delims=" %%r in ('type myfile.txt') do (
    set /a lineCount+=1
    call set line[%%lineCount%%]=%%r
    )
  echo The number of lines is %lineCount%
  for /L %%i in (1,1,%lineCount%) do call echo %%i %%line[%%i]%%
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  The number of lines is 4
  1 This is the first line
  2 This is the second line
  3 This is the third line
  4 This is the fourth line
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:11 2008
Subject: 11) How do I retain my original code page in these scripts?
Date: Thu,  6 Mar 2008 01:00:11
From: ts@uwasa.fi (Timo Salmi)

  @echo off
  for /f "tokens=3 delims= " %%p in (
    'mode con: codepage /status ^| find "Code page"') do (
    set store_codepage_=%%p)
  echo The stored codepage is %store_codepage_%
  ::
  mode con: codepage select=850
  echo Whatever ...
  ::
  mode con: codepage select=%store_codepage_%
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:12 2008
Subject: 12) How can I rename all my .JPG files sequentially in a folder?
Date: Thu,  6 Mar 2008 01:00:12
From: ts@uwasa.fi (Timo Salmi)

This is an instructive task, so let's go through it in several
intermediate steps. First consider
  @echo off
  set count_=1
  for /f %%f in ('dir c:\_g\www\~ts\gallery\*.jpg /b /s /-c /a:-d-s-h') do (
    call :_subru1 %%f)
  set count_=
  echo End of the first test
  goto :EOF
  ::
  :_subru1
  echo %count_% %~d1 %~p1 %~n1 %~x1
  set /a count_+=1
  goto :EOF
A screen capture would turn out something like below to demonstrate
some of the ~ modifiers on variables. The example also
demonstrates incrementing the value of an environment variable
(count_)  in a loop-like manner.
   1 c: \_G\WWW\~TS\GALLERY\ ABSORB .JPG
   2 c: \_G\WWW\~TS\GALLERY\ ABSORB_ .JPG
   3 c: \_G\WWW\~TS\GALLERY\ BIKEMIR .JPG
   4 c: \_G\WWW\~TS\GALLERY\ CATEYE .JPG
   5 c: \_G\WWW\~TS\GALLERY\ CATEYE_ .JPG
   6 c: \_G\WWW\~TS\GALLERY\ CRESBAG .JPG
   7 c: \_G\WWW\~TS\GALLERY\ CRESBAG_ .JPG
   8 c: \_G\WWW\~TS\GALLERY\ CRESCE2 .JPG
   9 c: \_G\WWW\~TS\GALLERY\ CRESCE2_ .JPG
   10 c: \_G\WWW\~TS\GALLERY\ CRESCENT .JPG
   :
   58 c: \_G\WWW\~TS\GALLERY\ TIMOHM72 .JPG
   59 c: \_G\WWW\~TS\GALLERY\ TIMOHOME .JPG
   60 c: \_G\WWW\~TS\GALLERY\ TIMOPEDA .JPG
   61 c: \_G\WWW\~TS\GALLERY\ Timophp3 .jpg
   62 c: \_G\WWW\~TS\GALLERY\ WELLGO .JPG
   End of the first test
Next step. Let's be prudent and not do the actual renaming but
instead create the scripts commands for the purpose:
  @echo off
  set count_=1
  for /f %%f in ('dir c:\_g\www\~ts\gallery\*.jpg /b /s /-c /a:-d-s-h') do (
    call :_subru1 %%f)
  set count_=
  echo End of the second test
  goto :EOF
  ::
  :_subru1
  setlocal
    set dr_=%~d1& set pth_=%~p1& set base_=%~n1& set ext_=%~x1
    echo @ren %dr_%%pth_%%base_%%ext_% %base_%.%count_%%ext_%
  endlocal
  set /a count_+=1
  goto :EOF
We would get
  D:\TEST>cmdfaq
  @ren c:\_G\WWW\~TS\GALLERY\ABSORB.JPG ABSORB.1.JPG
  @ren c:\_G\WWW\~TS\GALLERY\ABSORB_.JPG ABSORB_.2.JPG
  @ren c:\_G\WWW\~TS\GALLERY\BIKEMIR.JPG BIKEMIR.3.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CATEYE.JPG CATEYE.4.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CATEYE_.JPG CATEYE_.5.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CRESBAG.JPG CRESBAG.6.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CRESBAG_.JPG CRESBAG_.7.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CRESCE2.JPG CRESCE2.8.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CRESCE2_.JPG CRESCE2_.9.JPG
  @ren c:\_G\WWW\~TS\GALLERY\CRESCENT.JPG CRESCENT.10.JPG
  :
  @ren c:\_G\WWW\~TS\GALLERY\TIMOHM72.JPG TIMOHM72.58.JPG
  @ren c:\_G\WWW\~TS\GALLERY\TIMOHOME.JPG TIMOHOME.59.JPG
  @ren c:\_G\WWW\~TS\GALLERY\TIMOPEDA.JPG TIMOPEDA.60.JPG
  @ren c:\_G\WWW\~TS\GALLERY\Timophp3.jpg Timophp3.61.jpg
  @ren c:\_G\WWW\~TS\GALLERY\WELLGO.JPG WELLGO.62.JPG
  End of the second test
OK, but that is not quite all what we want. Let's finish by adding
leading zeroes so that the number always is four digits long.
  @echo off
  :: requires GAWK to set the leading zeros
  set count_=1
  for /f %%f in ('dir "c:\_g\www\~ts\gallery\*.jpg" /b /s /-c /a:-d-s-h') do (
    call :_subru1 %%f)
  set count_=
  if exist "%TEMP%\tmp$$$.cmd" del "%TEMP%\tmp$$$.cmd"
  echo End of the concluding test ^(with gawk^)
  goto :EOF
  ::
  :_subru1
  setlocal
    set dr_=%~d1& set pth_=%~p1& set base_=%~n1& set ext_=%~x1
    echo %count_%|gawk '{printf "@set leadnro_=%%04d\n",$0}'>"%TEMP%\tmp$$$.cmd"
    call "%TEMP%\tmp$$$.cmd"
    echo @ren "%dr_%%pth_%%base_%%ext_%" "%base_%.%leadnro_%%ext_%"
  endlocal
  set /a count_+=1
  goto :EOF
And the corresponding output
  D:\TEST>cmdfaq
  @ren "c:\_G\WWW\~TS\GALLERY\ABSORB.JPG" "ABSORB.0001.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\ABSORB_.JPG" "ABSORB_.0002.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\BIKEMIR.JPG" "BIKEMIR.0003.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CATEYE.JPG" "CATEYE.0004.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CATEYE_.JPG" "CATEYE_.0005.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CRESBAG.JPG" "CRESBAG.0006.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CRESBAG_.JPG" "CRESBAG_.0007.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CRESCE2.JPG" "CRESCE2.0008.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CRESCE2_.JPG" "CRESCE2_.0009.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\CRESCENT.JPG" "CRESCENT.0010.JPG"
  :
  @ren "c:\_G\WWW\~TS\GALLERY\TIMOHM72.JPG" "TIMOHM72.0058.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\TIMOHOME.JPG" "TIMOHOME.0059.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\TIMOPEDA.JPG" "TIMOPEDA.0060.JPG"
  @ren "c:\_G\WWW\~TS\GALLERY\Timophp3.jpg" "Timophp3.0061.jpg"
  @ren "c:\_G\WWW\~TS\GALLERY\WELLGO.JPG" "WELLGO.0062.JPG"
  End of the concluding test

The gawk line could be formulated in other ways as well. For example
the more complicated
  gawk '{i="0000"$1}{p=length(i)}{printf "@set leadnro_=%%s\n",substr(i,p-3,p)}'

The leading zeros could be inserted with plain script only without
using gawk. It goes like this
  @echo off
  set count_=1
  for /f %%f in ('dir "c:\_g\www\~ts\gallery\*.jpg" /b /s /-c /a:-d-s-h') do (
    call :_subru1 %%f)
  set count_=
  if exist "%TEMP%\tmp$$$.cmd" del "%TEMP%\tmp$$$.cmd"
  echo End of the concluding test ^(without gawk^)
  goto :EOF
  ::
  :_subru1
  setlocal
    set dr_=%~d1& set pth_=%~p1& set base_=%~n1& set ext_=%~x1
    if %count_% LSS 10 set leadnro_=000%count_%
    if %count_% LSS 100 IF %count_% GEQ 10 set leadnro_=00%count_%
    if %count_% LSS 1000 IF %count_% GEQ 100 set leadnro_=0%count_%
    if %count_% GEQ 1000 set leadnro_=%count_%
    echo @ren "%dr_%%pth_%%base_%%ext_%" "%base_%.%leadnro_%%ext_%"
  endlocal
  set /a count_+=1
  goto :EOF

There is a better, special method for the right justification. See
the usage FuncRightJustify function which is part of the WHEREIS.CMD
script included in this collection. (It uses spaces instead of
zeros.)
  :FuncRightJustify arg1 arg2
  setlocal enableextensions
    set number_=            %1
    set number_=%number_:~-12%
  endlocal & set "%2=%number_%" & Goto :EOF

LIMITATIONS: If you use paths, like I did in the above examples,
then you must include the all subfolders switch /s to get at the
correct full path. Alternatively, you could drop the /s but then you
must run the script in the folder where your relevant *.JPG files
are. Else you will get incorrect paths.

References/Comments:
 http://www.google.com/groups?selm=6SWIb.34109%24_P.1466245%40news4.tin.it
Dr. John Stockton: "To get always 4 digits, one way is to count from
10001 and take the last 4 of the 5 characters. Or just to number
from 10001 or 10000."
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:13 2008
Subject: 13) How do I get the current day of the week?
Date: Thu,  6 Mar 2008 01:00:13
From: ts@uwasa.fi (Timo Salmi)

For today we have
  @echo off & setlocal enableextensions
  rem Requires gawk
  gawk 'BEGIN{printf"@set wd_=%%s\n",strftime("%%a")}'>"%TEMP%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%TEMP%\tmp$$$.cmd"
  echo The weekday today is %wd_%
  set wd_=
  endlocal & goto :EOF
The output could be e.g.
  C:\_D\TEST>cmdfaq
  The weekday today is Thu

For yesterday
  @echo off & setlocal enableextensions
  rem Requires gawk
  gawk 'BEGIN{printf"@set wd_=%%s\n",strftime("%%a",systime()-24*60*60)}'>"%TEMP%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%TEMP%\tmp$$$.cmd"
  echo The weekday yesterday was %wd_%
  endlocal & goto :EOF
The output could be e.g.
  C:\_D\TEST>cmdfaq
  The weekday yesterday was Wed

Another option for today's weekday is
  @echo off
  ::
  :: Get and show today's Julian date number
  :: Requires DATE2NUM.EXE from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
  DATE2NUM /set>"%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  echo datenum_=%datenum_%
  ::
  :: Convert the result into a weekday number (Mon=1 to Sun=7)
  set /a wd_=(%datenum_% %% 7) + 1
  echo wd_=%wd_%
  ::
  :: Convert the weekday into three letters
  for /f "tokens=%wd_%" %%d in ('echo Mon Tue Wed Thu Fri Sat Sun') do echo %%d
  ::
  :: Clean up
  for %%v in (datenum_ wd_) do set %%v=
The output on Thu 30-Jun-2005 would have been
  C:\_D\TEST>cmdfaq
  datenum_=2453552
  wd_=4
  Thu

Apropos %mytemp%. If not (pre)set, the temporary files will go to
the root directory.

The problem can also be solved with a Visual Basic Script (VBScript)
aided command line script
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo tmp$$$.vbs
  :: Call the command line script the script host built
  call tmp$$$.cmd
  :: Clean up
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  :: Show the result
  echo wd_=%wd_%
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  Const ForReading = 1, ForWriting = 2, ForAppending = 8             'VBS
  Dim DateNow, fso, f                                                'VBS
  DateNow = Date                                                     'VBS
  Set fso = CreateObject("Scripting.FileSystemObject")               'VBS
  Set f = fso.OpenTextFile("tmp$$$.cmd", ForWriting, True)           'VBS
  f.Write "@set wd_=" & WeekDayName(Weekday(DateNow),true)           'VBS
  f.Close                                                            'VBS

Or, more concisely
  @echo off & setlocal enableextensions
  if not exist c:\mytemp mkdir c:\mytemp
  echo>c:\mytemp\tmp$$$.vbs WScript.Echo WeekDayName(Weekday(Date),true)
  for /f %%d in ('cscript //nologo c:\mytemp\tmp$$$.vbs') do set wd_=%%d
  for %%f in (c:\mytemp\tmp$$$.vbs) do if exist %%f del %%f
  rmdir c:\mytemp
  echo Weekday wd_=%wd_%
  endlocal & goto :EOF
The output could be e.g.
  D:\TEST>cmdfaq
  Weekday wd_=Thu

Using a number to indicate the weekday instead of the letters
  @echo off & setlocal enableextensions
  if not exist c:\mytemp mkdir c:\mytemp
  echo>c:\mytemp\tmp$$$.vbs WScript.Echo Weekday(Date,vbMonday)
  for /f %%d in ('cscript //nologo c:\mytemp\tmp$$$.vbs') do set wd_=%%d
  for %%f in (c:\mytemp\tmp$$$.vbs) do if exist %%f del %%f
  rmdir c:\mytemp
  echo Weekday number ^(with Monday as 1^) wd_=%wd_%
  endlocal & goto :EOF
The output could be e.g.
  D:\TEST>cmdfaq
  Weekday number (with Monday as 1) wd_=4
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:14 2008
Subject: 14) Help! My old batch files won't work since there is no choice.
Date: Thu,  6 Mar 2008 01:00:14
From: ts@uwasa.fi (Timo Salmi)

 Q: When I try to run my old batch file as a CMD.EXE script I get
"'choice' is not recognized as an internal or external command,
operable program or batch file." What can I do?

 A: The CHOICE command has been dropped because it can cause
collisions in the NT/2000/XP multi-tasking environment. Thus the
best choice (if you pardon the pun) is not try to find an old
version, but patiently write your scripts anew using SET /P. Below
is a simple demonstration
  @echo off
  setlocal
  :_again
  set /p ask_="Please respond [Y,N,Q]?"
  for %%a in (y n q) do if /i "%ask_%"=="%%a" goto _%%a
  goto _again
  ::
  :_y
  echo Your input was Yes& goto :EOF
  :_n
  echo Your input was No& goto :EOF
  :_q
  echo Your input was Quit& goto :EOF
  endlocal

However, you might try a clone such as CHOOSE.EXE "Ask questions in
batch/script files" from ftp://garbo.uwasa.fi/pc/ts/tsutlf17.zip or
later. (Now also included in tscmd.zip)
  @echo off & setlocal enableextensions
  choose /tq,5 /cynq "Give your answer "
  if errorlevel==0 if not errorlevel==1 echo You effected a break
  if errorlevel==1 if not errorlevel==2 echo Your input was Yes
  if errorlevel==2 if not errorlevel==3 echo Your input was No
  if errorlevel==3 if not errorlevel==4 echo Your input was Quit
  if errorlevel==255 echo Error condition
  endlocal & goto :EOF

Alternatively
  @echo off & setlocal enableextensions
  choose /tq,5 /cynq /x "Give your answer "
  for %%c in (call del) do %%c choose_.bat
  if "%choose_%"=="0" echo You effected a break
  if "%choose_%"=="1" echo Your input was Yes
  if "%choose_%"=="2" echo Your input was No
  if "%choose_%"=="3" echo Your input was Quit
  if "%choose_%"=="255" echo Error condition
  endlocal & goto :EOF

The output in both the cases might be e.g.
  D:\TEST>cmdfaq
  Give your answer [Y,N,Q]?Q
  Your input was Quit

The obvious advantage of CHOOSE.EXE over the SET /P method is that
the former can handle timed default input.

If you want Microsoft's old CHOICE.EXE it seems to be available from
the Microsoft Windows 98 Resource Kit e.g. at
ftp://ftp.microsoft.com/Services/TechNet/samples/PS/Win98/Reskit/SCRPTING
(For the tools included with the Microsoft Windows 98 Resource Kit
see http://support.microsoft.com/kb/247024)

References/Comments:
 http://www.google.com/groups?selm=3E1C6329.5020008%40uclink.berkeley.edu
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:15 2008
Subject: 15) Is it possible to echo without linefeed like the Unix echo -n?
Date: Thu,  6 Mar 2008 01:00:15
From: ts@uwasa.fi (Timo Salmi)

At least with gawk, yes. The following example script demonstrates
  @echo off
  echo Testline 1|gawk '{printf"%%s",$0}'
  echo Testline 2|gawk '{printf"%%s",$0}'
  echo Testline 3|gawk '{printf"%%s\n",$0}'

Related subject: Re: Combining two single-line files into one single-line file
Q: The following question was posed on the Usenet news:
  File1.txt contains: Asset #353
  File2.txt contains: 3-25-02
  I want File3.txt to contain: Asset #353 3-25-02
A: One, but not the only option is
  @echo off
  <File1.txt gawk '{printf"%%s",$0}'>File3.txt
  <File2.txt gawk '{printf" %%s\n",$0}'>>File3.txt

The sister package for MS-DOS+Win..95/98/ME
 ftp://garbo.uwasa.fi/pc/link/btsbat.zip
 Useful MS-DOS batch files and tricks, T.Salmi
contains ECHON.EXE "echo -n, Echo without a linefeed"
which works also on NT/2000/XP (or at least XP, since I can't test
the others).

  @echo off & setlocal enableextensions
  C:\_F\BAT\ECHON Testline 1
  C:\_F\BAT\ECHON Testline 2
  C:\_F\BAT\ECHON Testline 3
  endlocal & goto :EOF

The output:
  D:\TEST>cmdfaq
  Testline 1Testline 2Testline 3

Many of the tsbat.zip solutions not necessarily included in
tscmd.zip work for  NT/2000/XP. However, the reverse is not true.
Most of the code in tscmd.zip is not valid for MS-DOS+Win..95/98/Me.

References/Comments:
 http://www.google.com/groups?selm=%23qRDtfqtBHA.2608%40tkmsftngp04
 http://www.google.com/groups?selm=bsm4uq%24e6f4a%241%40ID-55492.news.uni-berlin.de
The solutions in the comment demonstrate that this task can be
solved without external tools. The solution below is based on Phil's
posting. Note the ^quoting of 1, 2, and 3 lest they be taken as
handles.

  @echo off & setlocal
  echo.|set /p=Testline ^1>tmp.txt
  echo.|set /p=Testline ^2>>tmp.txt
  echo.Testline ^3>>tmp.txt
  for %%c in (type del) do %%c tmp.txt
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  Testline 1 Testline 2 Testline 3

Alternatively
  @echo off & setlocal enableextensions
  <nul (set /p z="Testline 1 ")>tmp.txt
  <nul (set /p z="Testline 2 ")>>tmp.txt
  <nul (set /p z="Testline 3")>>tmp.txt
  echo.>>tmp.txt
  for %%c in (type del) do %%c tmp.txt
  endlocal & goto :EOF

As an aside, if for some unfathomable reason you want to create a
file of 1 byte (one, not two) then
  @echo off & setlocal enableextensions
  echo.|set /p=>myfile
  dir myfile
  endlocal & goto :EOF

The original problem can also be solved with a Visual Basic Script
(VBScript) aided command line script
  @echo off & setlocal enableextensions
  > tmp$$$.vbs echo WScript.StdOut.Write "Prof. "
  >>tmp$$$.vbs echo WScript.StdOut.Write "Timo Salmi, "
  >>tmp$$$.vbs echo WScript.StdOut.Write "University of Vaasa, "
  >>tmp$$$.vbs echo WScript.StdOut.WriteLine "Finland"
  cscript //nologo tmp$$$.vbs
  echo See, it works!
  for %%f in (tmp$$$.vbs) do if exist %%f del %%f
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  Prof. Timo Salmi, University of Vaasa, Finland
  See, it works!
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:16 2008
Subject: 16) How can I get the time without having to press enter?
Date: Thu,  6 Mar 2008 01:00:16
From: ts@uwasa.fi (Timo Salmi)

Version independently
  @echo off
  echo.| time | find /v "new"
For example you might get
  The current time is:  8:46:29.15

However, in scripting the date and time variables are directly
available
  @echo off
  echo %time%
In this option you might get for example
  D:\TEST>cmdfaq
   9:03:13.56

Also
  @echo off
  time /t
which would produce e.g.
  D:\TEST>cmdfaq
  09:03

There is a complication, however. Say that you wish to capture the
hour, alone. One has to take into account that the hour might have
one or two digits. One can't safely use %time:~0,2% so instead use
the for /f method:
  @echo off & setlocal enableextensions
  for /f "tokens=1 delims=:. " %%h in ("%time%") do set hh_=%%h
  echo %hh_%
  endlocal & goto :EOF
The output would be e.g.
  D:\TEST>cmdfaq
  9

If you want the potential leading zero, use TIME /T as follows
  @echo off & setlocal enableextensions
  for /f "tokens=1 delims=:. " %%h in ('time /t') do set hh_=%%h
  echo %hh_%
  endlocal & goto :EOF
The output would be e.g.
  D:\TEST>cmdfaq
  09

Another option
  @echo off & setlocal enableextensions
  ::
  :: Put the time in an auxiliary variable to fix the moment
  set time_=%time%
  ::
  :: Take care of the potential leading space for small hours
  set time_=%time_: =0%
  ::
  :: Extract the time elements
  set hh_=%time_:~0,2%
  set mn_=%time_:~3,2%
  set ss_=%time_:~6,2%
  set s100_=%time_:~9,2%
  ::
  :: Display
  echo %hh_% %mn_% %ss_% %s100_%
  endlocal & goto :EOF
The output might be e.g.
  D:\TEST>cmdfaq
  09 58 51 06

There are other options, including a Visual Basic Script aided
command line script like the one already presented in item #1 about
the date variables.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:17 2008
Subject: 17) How can I avoid the potential "ECHO is off." in echoing %myvar%
Date: Thu,  6 Mar 2008 01:00:17
From: ts@uwasa.fi (Timo Salmi)

Use a period right after the echo.
  @echo off
  setlocal
  set myvar=This is a test
  echo.%myvar%
  set myvar=
  echo.%myvar%
  echo That's all
  endlocal

Which gives
  D:\TEST>cmdfaq
  This is a test

  That's all
Without the period (.) you'd get
  D:\TEST>cmdfaq
  This is a test
  ECHO is off.
  That's all
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:18 2008
Subject: 18) How does one build re-usable script function modules?
Date: Thu,  6 Mar 2008 01:00:18
From: ts@uwasa.fi (Timo Salmi)

The best way to get started is making the simplest possible example.
Let's build and test one script function for addition and one for
subtraction. The arguments are passed by reference.

  @echo off
  setlocal enableextensions
  call :FuncAdd 3 5 sum_
  echo The sum is %sum_%
  call :FuncSub 3 5 diff_
  echo The difference is %diff_%
  goto :EOF

  :FuncAdd arg1_ arg2_ return_
  setlocal enableextensions
    set /a return_=%1+%2
  endlocal & set "%3=%return_%" & goto :EOF

  :FuncSub arg1_ arg2_ return_
  setlocal enableextensions
    set /a return_=%1-%2
  endlocal & set "%3=%return_%" & goto :EOF

The output:
  D:\TEST>cmdfaq
  The sum is 8
  The difference is -2
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:19 2008
Subject: 19) How can one build a delay / sleep / wait procedure for a script?
Date: Thu,  6 Mar 2008 01:00:19
From: ts@uwasa.fi (Timo Salmi)

One method is to observe the difference between time the delay is
started and the current time. The calculations are in hundreds of a
second since midnight. (The rare potential case of straddling the
midnight is not covered.) The example below sleeps for about two and
a half seconds.

  @echo off & setlocal enableextensions
  echo %time%
  call :ProcDelay 250
  echo %time%
  endlocal & goto :EOF

  :ProcDelay delayMSec_
  setlocal enableextensions
    set time_=%time%
    set time_=%time_::0=:%
    set time_=%time_:.0=.%
    set time_=%time_: =%
    for /f "tokens=1-4 delims=:. " %%h in ('echo %time_%') do (
      set /a start_=360000*%%h+6000*%%i+100*%%j+%%k)
    :_procwaitloop
      set time_=%time%
      set time_=%time_::0=:%
      set time_=%time_:.0=.%
      set time_=%time_: =%
      for /f "tokens=1-4 delims=:. " %%h in ('echo %time_%') do (
        set /a now_=360000*%%h+6000*%%i+100*%%j+%%k)
      set /a diff_=%now_%-%start_%+3
    if %diff_% LSS %1 goto _procwaitloop
  endlocal & goto :EOF

The output e.g:
  D:\TEST>cmdfaq
  19:49:06.94
  19:49:09.45

Why the set time_=%time_::0=:% lines? To avoid the octal number
catch. Octals are (confusingly) identified by a leading zero.

There is another, alternative. For a two second delay one can try to
ping oneself as follows

 @echo off
 ping -n 3 127.0.0.1>nul
which would produce e.g.
  D:\TEST>cmdfaq
  15:24:47.57
  15:24:49.62
As you see, it is not dead accurate. But neither is the first
solution. Not that it is essential.

Furthermore, you could have
  @echo off & setlocal enableextensions enabledelayedexpansion
  echo WScript.Sleep 1000 > "%temp%\tmp$$$.vbs"
  echo %time%
  cscript //nologo "%temp%\tmp$$$.vbs"
  echo %time%
  for %%f in ("%temp%\tmp$$$.vbs") do if exist %%f del %%f
  endlocal & goto :EOF
which would produce e.g.
  D:\TEST>cmdfaq
  13:13:03.00
  13:13:04.07
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:20 2008
Subject: 20) Is is possible to right-justify numbers or words in a script?
Date: Thu,  6 Mar 2008 01:00:20
From: ts@uwasa.fi (Timo Salmi)

Yes. See the subru1_ in item #12 "How can I rename all my .JPG files
sequentially in a folder?" and the FuncRightJustify routine in
WHEREIS.CMD script included in this collection. Also see the lines
  set fsize_=         %%~zf
  set fsize_=!fsize_:~-10!
in item #8. This method is reasonably simple, unlike some earlier
solutions presented.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:21 2008
Subject: 21) Do you have pointers to additional script material and tips?
Date: Thu,  6 Mar 2008 01:00:21
From: ts@uwasa.fi (Timo Salmi)

Yes, some. But since the links to outside material may (or may not)
be transient and volatile in nature I will rather point to a web
page of mine carrying references to programming material. Link
directly to either
  http://www.uwasa.fi/~ts/http/http2.html#programming
  http://www.uwasa.fi/~ts/http/http2.html#cmdscript

Where do I find a detailed command-line reference?
  Left-click "start" in the Taskbar
   Enter "Command-line reference" into the Search window
    Two suggested topics should appear
     Choose from "Overviews, Articles and Tutorials"
      Click "Add to Favorites" to quickly locate the item in the future

Here are some other useful NT/2000/XP CMD.EXE command line scripts
programming pointers and links related to this FAQ

  Windows own command-line reference also: hh C:\WINDOWS\Help\ntcmds.chm
  The location may vary depending your particular configuration.
  If so, try the included WHEREIS.CMD script.

  xx) How do I control echoing in batch files? (Walter Briscoe)
  http://groups.google.com/group/comp.archives.ms-windows.discuss/msg/534d2e122c3f88b6

  Oct 28 2004 Dave Jenkins in
  Jan 11 2005 David Devore in
  ftp://garbo.uwasa.fi/pc/pd2/tspost28.zip
  tspost28.zip Information email + postings, from 19-Sep-00 to ...

More generally:
  Miscellaneous questions, information and comments about Timo's
  programs etc.  http://www.uwasa.fi/~ts/garbo.html#faqtimo

 ftp://garbo.uwasa.fi/pc/pd2/tspost00.zip
 Index for Timo's FAQs and Information email + postings

 ftp://garbo.uwasa.fi/pc/pd2/tspost28.zip
 Information email + postings, from 19-Sep-00 to ...

Newsgroups (here in the Google format) including
  http://www.google.com/groups?group=alt.msdos.batch.nt
  http://www.google.com/groups?group=microsoft.public.win2000.cmdprompt.admin
For more on newsgroups, see e.g.
  http://www.uwasa.fi/~ts/http/news.html#programming
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:21 2008
Subject: 22) How do I capture the current folder name into a variable?
Date: Thu,  6 Mar 2008 01:00:21
From: ts@uwasa.fi (Timo Salmi)

The second line below shows the trick
  @echo off
  for /f "tokens=*" %%d in ('cd') do set currdir_=%%d
  echo %currdir_%
  set currdir_=
The output might be
 C:\Documents and Settings\ts\Local Settings\Temp>D:\TEST\cmdfaq
 C:\Documents and Settings\ts\Local Settings\Temp

The "tokens=*" full coverage is crucial with long path names where
spaces are possible. Without it the name is cut at the first space.
In the example the result would have erroneously been
 C:\Documents and Settings\ts\Local Settings\Temp>D:\TEST\cmdfaq
 C:\Documents

Note the difference from
  set scriptdir_=%~dp0
  echo %scriptdir_%
  set scriptdir_=
which would give the path of the calling script (see item #5).

As a demonstration of the current folder usage consider the
following little snippet
  @echo off
  setlocal enableextensions
    for /f "tokens=*" %%d in ('cd') do set currdir_=%%d
    pushd %currdir_%
    cd
    c:
    cd \Documents and Settings
    cd
    popd
    cd
  endlocal & goto :EOF
which would produce something like
  D:\TEST>cmdfaq
  D:\TEST
  C:\Documents and Settings
  D:\TEST
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:23 2008
Subject: 23) How do I get the n'th, the first and the last line of a text file?
Date: Thu,  6 Mar 2008 01:00:23
From: ts@uwasa.fi (Timo Salmi)

For one solution see the test below. (For the first line one would
naturally just set the line number as 1).
  @echo off
  setlocal enableextensions
  ::
  :: Make a test file
  echo   word11 word12 word13 word14>mytest.txt
  for %%i in (2 3 4 5 6 7 8 9) do echo   word%%i1  word%%i2 word%%i3 word%%i4>>mytest.txt
  ::
  :: Do the test. Get the fifth line.
  call :ProcGetLine mytest.txt 5 getLine
  echo %getLine%
  ::
  :: Another test. Get the last line
  call :ProcGetLastLine mytest.txt getLine
  echo %getLine%
  ::
  :: Clean up
  for %%f in (mytest.txt) do if exist %%f del %%f
  endlocal & goto :EOF

  ::===============================================================
  :ProcGetLine FileName LineNro returnText
  setlocal enableextensions
  set lineNro_=%2
  set /a lineNro_-=1
  set return_=
  for /f "tokens=* skip=%lineNro_% delims=" %%r in ('type %1') do (
    if not defined return_ set return_=%%r)
  endlocal & set %3=%return_% & goto :EOF

  ::===============================================================
  :ProcGetLastLine FileName returnText
  setlocal enableextensions
  for /f "tokens=* delims=" %%r in ('type %1') do (
    set return_=%%r)
  endlocal & set %2=%return_% & goto :EOF

The output:
  D:\TEST>cmdfaq
    word51  word52 word53 word54
    word91  word92 word93 word94

There are other options like
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>mytest.txt
  ::
  :: Special get the first line of a file
  set /p line_=<mytest.txt
  echo %line_%
  ::
  :: Special get the last file of a file
  for /f "delims=" %%r in ('type mytest.txt') do set line_=%%r
  echo %line_%
  ::
  :: Special get the Nth line
  set /a n_=5-1
  for /f "skip=%n_% delims=" %%r in ('type mytest.txt') do echo %%r>>mytemp.txt
  set /p line_=<mytemp.txt
  echo %line_%
  ::
  :: Clean up
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  endlocal & goto :EOF

The output is
  D:\TEST>cmdfaq
  This is line 1
  This is line 9
  This is line 5

The solution options do not stop here. Also SED and G(nu)AWK could
be used in this and the following item. But in NT/2000/XP scripting
that is not really necessary. If you are nevertheless interested
there are several items that extract and manipulate lines in
ftp://garbo.uwasa.fi/pc/link/tsbat.zip in one way or the other.

References/Comments:
 http://www.google.com/groups?selm=bt0qg6%242618r%241%40ID-55492.news.uni-berlin.de
 http://www.google.com/groups?selm=bt1iq4%242cafm%241%40ID-55492.news.uni-berlin.de
Using Phil Robyn's referenced, faster solution we would have
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>mytest.txt
  ::
  for /f %%a in ('find /v /c "" ^< mytest.txt') do set /a linecount=%%a
  set /a linecount-=1
  for /f "tokens=*" %%a in ('more /e +%linecount% mytest.txt') do set last_line=%%a
  echo %last_line%
  ::
  :: Clean up
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  endlocal & goto :EOF
The output is
  D:\TEST>cmdfaq
  This is line 9

Still another version for getting the N'th line. Not necessarily
efficient, but nicely demonstrates some of the command line script
facets.
  @echo off & setlocal enableextensions enabledelayedexpansion
  :: Make a test file
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>mytest.txt
  ::
  set /a GetLineNumber=5
  for /f "tokens=1,* delims=:" %%a in ('findstr /n "\<*" "mytest.txt"') do (
    set /a LineCount_=%%a
    if !LineCount_! EQU %GetLineNumber% set line_=%%b)
  echo %line_%
  ::
  :: Clean up
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  This is line 5

Alternatively, the more straight-forward
  @echo off & setlocal enableextensions enabledelayedexpansion
  :: Make a test file
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>mytest.txt
  ::
  set /a GetLineNumber=5
  for /f "tokens=* delims=" %%r in ('type "mytest.txt"') do (
    set /a LineCount_+=1
    if !LineCount_! EQU %GetLineNumber% set line_=%%r)
  echo %line_%
  ::
  :: Clean up
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  endlocal & goto :EOF
The output is
  D:\TEST>cmdfaq
  This is line 5

So far so good, but one crucial question remains, especially if the
text file is big. Which is the fastest (or fast enough) method. This
aspect has been worked out by Phil Robyn in
 http://www.google.com/groups?selm=bt1l3n%242d6k5%241%40ID-55492.news.uni-berlin.de
The example below rests heavily on his posting, but is rewritten to
fit the standard style in this FAQ
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>mytest.txt
  ::
  :: Which line?
  set /a GetLineNumber=5
  ::
  :: Perform the actual task (Due to Phil Robyn)
  set /a StartAt = GetLineNumber - 1
  more /e +%StartAt% mytest.txt>mytemp.txt
  set /p Nth_line=<mytemp.txt
  ::
  :: Show the result (note the . right after echo for empty lines)
  echo.%Nth_line%
  ::
  :: Clean up
  for %%f in (mytest.txt mytemp.txt) do if exist %%f del %%f
  endlocal & goto :EOF
The output is
  C:\_D\TEST>cmdfaq
  This is line 5

References/Comments:
 http://www.google.com/groups?selm=YXcKb.42470%24VW.1935675%40news3.tin.it

There is a catch, though, to the solutions for far in this item. The
potential empty lines are ignored! See item #64 for more. Also see
item #70.

Alternatively, a Visual Basic aided command line script solution
could be used for a generic solution to output the lines of a text
file starting from n1 and ending with n2. It does not have the empty
lines discrepancy problem.
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  for %%i in (1 2 3 4 5 6) do echo This is line %%i>>myfile.txt
  echo.>>myfile.txt
  for %%i in (8 9 10 11 12) do echo This is line %%i>>myfile.txt
  ::
  :: Build a Visual Basic Script
  if not exist c:\mytemp mkdir c:\mytemp
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  ::
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs < myfile.txt
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs myfile.txt) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  n1 = 5 'VBS
  n2 = 8 'VBS
  '
  i = 0 'VBS
  Do While Not WScript.StdIn.AtEndOfStream 'VBS
    i = i + 1 'VBS
    If i > n2 Then Exit Do 'VBS
    str = WScript.StdIn.ReadLine 'VBS
    If i >= n1 Then : WScript.StdOut.WriteLine str : End If 'VBS
  Loop 'VBS

The output will be
  D:\TEST>cmdfaq
  This is line 5
  This is line 6

  This is line 8
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:24 2008
Subject: 24) How do I get the m'th item on the n'th line of a text file?
Date: Thu,  6 Mar 2008 01:00:24
From: ts@uwasa.fi (Timo Salmi)

The obvious, related question "How do I get the m'th item on the
n'th line of a text file?" is easily answered complementing the
previous item on getting the n'th line.

  :: Do the test. Get the third word of the fifth line.
  call :ProcGetLine mytest.txt 5 getLine
  for /f "tokens=3" %%? in ("%getLine%") do echo %%?

In full:
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  echo   word11 word12 word13 word14>mytest.txt
  for %%i in (2 3 4 5 6 7 8 9) do echo   word%%i1  word%%i2 word%%i3 word%%i4>>mytest.txt
  ::
  :: Do the test. Get the third word of the fifth line.
  call :ProcGetLine mytest.txt 5 getLine
  for /f "tokens=3" %%? in ("%getLine%") do echo %%?
  ::
  :: Clean up
  for %%f in (mytest.txt) do if exist %%f del %%f
  endlocal & goto :EOF
  ::===============================================================
  :ProcGetLine FileName LineNro returnText
  setlocal enableextensions
  set lineNro_=%2
  set /a lineNro_-=1
  set return_=
  for /f "tokens=* skip=%lineNro_% delims=" %%r in ('type %1') do (
    if not defined return_ set return_=%%r)
  endlocal & set %3=%return_% & goto :EOF

Since the fifth line in mytest.txt is
    word51  word52 word53 word54
the output would be
  C:\_D\TEST>cmdfaq
  word53

Naturally, this could be programmed into the procedure instead of
doing it outside it as in the above.

Likewise, getting the characters on line 5 starting from the third
ending with the eleventh characters would be easy:
Replace
  for /f "tokens=3" %%? in ("%getLine%") do echo %%?
with
  echo.%getLine:~2,9%
Note, however, the slight complication that the first argument
starts from zero and the second is the number of characters. Also
note the point (.) after the echo to prevent a potential "ECHO is
off." message.

D:\TEST>cmdfaq
123456789 123456789 123456789
  word51  word52 word53 word54
word51  w

Another case:
> I have strings such as these:
>    'HELLO-1039-4019-3929'
>    'YES-1930-4910-4939'
> with a variable number of characters before the first hyphen. I'd
> like my command file to parse out and return to me the string
> 'HELLO' or 'YES': whatever exists before the first hyphen. Can
> someone point me in the right direction of how to do this? Thanks
> much.

  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  echo HELLO-1039-4019-3929 > mytest.txt
  echo YES-1930-4910-4939 >> mytest.txt
  ::
  ::
  for /f "tokens=1 delims=-" %%a in ('type mytest.txt') do (
    echo %%a
  )
  ::
  :: Clean up
  for %%f in (mytest.txt) do if exist %%f del %%f
  endlocal & goto :EOF

Output:
  C:\_D\TEST>cmdfaq
  HELLO
  YES

References/Comments:
 http://www.google.com/groups?selm=432b81fb%240%2411615%249b536df3%40news.fv.fi
 http://www.google.com/groups?selm=dl4tc5%24ge4%242%40haavi.uwasa.fi
 http://www.google.com/groups?selm=dl560u%24jkl%242%40haavi.uwasa.fi
 http://www.google.com/groups?selm=43ed7935%240%2424104%249b536df3%40news.fv.fi
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:25 2008
Subject: 25) How can I quote with e.g. "> " an entire message?
Date: Thu,  6 Mar 2008 01:00:25
From: ts@uwasa.fi (Timo Salmi)

  @echo off
  ::
  :: Make a test file
  echo word11 word12 word13 word14>mytest.txt
  for %%i in (2 3 4 5 6 7 8 9) do echo word%%i1  word%%i2 word%%i3 word%%i4>>mytest.txt
  ::
  :: Do the test using "> " as the quote character
  for %%f in (mytestQuoted.txt) do if exist %%f del %%f
  for /f "tokens=* delims=" %%r in ('type mytest.txt') do (
    echo ^> %%r >> mytestQuoted.txt)
  type mytestQuoted.txt
  ::
  :: Clean up
  for %%f in (mytest.txt mytestQuoted.txt) do if exist %%f del %%f

The output:
  D:\TEST>cmdfaq
  > word11 word12 word13 word14
  > word21  word22 word23 word24
  > word31  word32 word33 word34
  > word41  word42 word43 word44
  > word51  word52 word53 word54
  > word61  word62 word63 word64
  > word71  word72 word73 word74
  > word81  word82 word83 word84
  > word91  word92 word93 word94
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:26 2008
Subject: 26) How do I get the length of a string into a variable?
Date: Thu,  6 Mar 2008 01:00:26
From: ts@uwasa.fi (Timo Salmi)

The method for getting the length of the string is to truncate a
copy of the string one character at a time (from the front) until
the copy becomes undefined, while at the same time keeping score of
the number of steps required. The possibility of an already empty
string must be taken into account.

  @echo off
  setlocal enableextensions
  set testString_=This is a test string
  call :GetLength %testString_%
  echo 123456789 123456789 123456789
  echo.%testString_%
  echo Length = %length_%
  goto :EOF
  ::
  ::===============================================================
  :GetLength
  setlocal enableextensions
    set rest_=%*
    set /a count_=0
    if not defined rest_ (set /a count_=-1 & set rest_=X)
    :_loop
      set /a count_+=1
      set rest_=%rest_:~1%
      if defined rest_ goto :_loop
  endlocal & set length_=%count_% & goto :EOF
The output:
  D:\TEST>cmdfaq
  123456789 123456789 123456789
  This is a test string
  Length = 21

Alternatively
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Get a test string
  if [%1]==[] (
    set s=This is a test string
    ) else (
    set s=%*
    )
  ::
  :: Get the length of the quoted string assuming a max of 255
  set charCount=0
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if defined si set /a charCount+=1)
  echo The length of "%s%" is %charCount% characters
  endlocal & goto :EOF
The output:
  D:\TEST>cmdfaq
  The length of "This is a test string" is 21 characters
Actually, the line "set si=!s:~%%c,1!" could be substituted with
just "set si=!s:~%%c!"

Another option is to write the string into a temporary file and get
that file's size (minus 2).
  @echo off & setlocal enableextensions
  set testString_=This is a test string
  echo %testString_%>"%temp%\length.tmp"
  for %%f in ("%temp%\length.tmp") do set length_=%%~zf
  for %%f in ("%temp%\length.tmp") do if exist %%f del %%f
  set /a length_ = %length_% - 2
  echo The length of "%testString_%" is %length_%
  endlocal & goto :EOF
The output is
  D:\TEST>cmdfaq
  The length of "This is a test string" is 21

A G(nu)AWK solution to the problem is
  @echo off & setlocal enableextensions
  set testString_=This is a test string
  if not exist c:\mytemp mkdir c:\mytemp
  echo %testString_%^
    |gawk "{printf\"@set length_=%%s\n\",length()}"^
    >c:\mytemp\length$$.cmd
  call c:\mytemp\length$$.cmd
  echo 123456789 123456789 123456789
  echo.%testString_%
  echo Length = %length_%
  set length_=
  del c:\mytemp\length$$.cmd
  rmdir c:\mytemp
  endlocal & goto :EOF
The output is
  D:\TEST>cmdfaq
  123456789 123456789 123456789
  This is a test string
  Length = 21
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:27 2008
Subject: 27) How can I remove all the blank lines from a text file?
Date: Thu,  6 Mar 2008 01:00:27
From: ts@uwasa.fi (Timo Salmi)

Several options will be presented. One script solution would be
  @echo off
  for %%f in (myfileNoBlanks.txt) do if exist %%f del %%f
  for /f "delims=" %%r in ('type myfile.txt') do echo.%%r>>myfileNoBlanks.txt

Using SED Stream EDitor is, however, the easiest method:
  @echo off
  sed "/^$/d" myfile.txt > myfileNobl.txt
However, using the native FINDSTR is equally easy. This regular
expression solution would appear to be the best, natural option.
  findstr /v "^$" MyFile.txt
Incidentally, note the difference with the literal option
  findstr /v /c:"^$" MyFile.txt
which, expectedly, will not solve the problem.

Likewise, GAWK could be used
  @echo off
  <myfile.txt gawk '{if(length($0)!=0)printf"%%s\n",$0}'
or
  @echo off
  gawk "{if(length()>0)printf\"%%s\n\",$0}" myfile.txt
or
  @echo off
  <myfile.txt gawk 'length()!=0'

If you wish to also define as an empty line a line that has nothing
but blanks or tabs on it, then use
  @echo off
  <myfile.txt sed "/^[\x09 ]*$/d"
or
  @echo off
  <myfile.txt gawk 'NF!=0'

OK, but what if you wish to remove all the lines that are two
characters or shorter. Or put in another way, you want to get all
the lines that are at least 3 characters long. This is one way how
to do it
  @echo off
  <myfile.txt gawk '{if(index(2-length(),"-"))printf"%%s\n",$0}'
or in abbreviated format
  @echo off
  <myfile.txt gawk 'index(2-length(),"-")'

For demonstration, the problem can also be solved with a Visual
Basic Script (VBScript) aided command line script. Use "Len(str) >
0" if the original task is being solved instead of the "two
characters or shorter".
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  for %%i in (1 2 3 4 5 6) do echo This is line %%i>>MyFile.txt
  echo ^7>>MyFile.txt
  echo.>>MyFile.txt
  for %%i in (9 10 11 12) do echo This is line %%i>>MyFile.txt
  ::
  :: Build a Visual Basic Script
  set skip=
  set vbs_="%temp%\tmp$$$.vbs"
  findstr "'%skip%VBS" "%~f0" > %vbs_%
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo %vbs_% < MyFile.txt
  ::
  :: Clean up
  for %%f in (%vbs_% MyFile.txt) do del %%f
  endlocal & goto :EOF
  '
  '.......................................................
  'The Visual Basic Script
  '
  Do While Not WScript.StdIn.AtEndOfStream            'VBS
    str = WScript.StdIn.ReadLine                      'VBS
    If Len(str) > 2 Then WScript.StdOut.WriteLine str 'VBS
  Loop                                                'VBS
The seventh and the eight lines will be skipped.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:28 2008
Subject: 28) How to convert a file written in IBM PC characters into LATIN1?
Date: Thu,  6 Mar 2008 01:00:28
From: ts@uwasa.fi (Timo Salmi)

This is another task, which is best suited for SED, the Stream
EDitor.

  @echo off
  setlocal enableextensions
  ::
  :: Covert IBM PC characters into LATIN1 characters
  :: Requires SED.EXE
  ::
  :: Make a test file with PC characters
  echo This is a test file in Finnish (which uses Scandinavian characters)>testin.txt
  echo Tm on testitiedosto ksten testaamiseksi.>>testin.txt
  echo Lis:  >>testin.txt
  echo >>testin.txt
  ::
  :: Optionally, create a SED command file
  echo.y//\xE5\xE4\xF6\xFC\xE9\xE7\xE6\xF1\xC5\xC4\xD6\xDC\xC9\xC7\xC6\xD1/>"%TEMP%\IBM2LAT1.SED"
  ::
  :: Do the conversion
  sed -f"%TEMP%\IBM2LAT1.SED" testin.txt  > testout.txt
  ::
  :: See that the result is what one expected
  notepad testout.txt
  ::
  :: Clean up
  for %%f in ("%TEMP%\IBM2LAT1.SED" testin.txt testout.txt) do if exist %%f del %%f
  endlocal & goto :EOF

However, the problem can also be solved with a Visual Basic Script.
VBScript has the advantage of being a part of the original XP
command environment. On the other hand the solution is clearly more
complicated than the very simple SED solution. Anyway, first, cut
and the following scrip. Name it e.g. IBM2LAT1.VBS and the call it
using

  CSCRIPT //NOLOGO IBM2LAT1 < MYIBM.TXT > MYLATIN1.TXT

  ' IBM2LAT1.VBS by Prof. Timo Salmi
  '
  ' Define the relevant characters
  Const IbmChar  = ""
  Const Lat1Char = ""
  '
  ' Define StandardIn and StandardOut
  Dim StdIn, StdOut
  Set StdIn = WScript.StdIn
  Set StdOut = WScript.StdOut
  '
  ' Convert one IBM character to Latin1
  Function CharIbm2Lat1(char)
    Dim p
    p = Instr (1, IbmChar, char, 1)
    if p > 0 Then
      CharIbm2Lat1 = Mid(Lat1Char, p, 1)
    Else
      CharIbm2Lat1 = char
    End If
  End Function
  '
  ' Convert a string
  Function Ibm2Lat1(str1)
    Dim str2
    For i = 1 To Len(str1)
      str2 = str2 & CharIbm2Lat1(Mid(str1,i,1))
    Next
    Ibm2Lat1 = str2
  End Function
  '
  ' Convert the input
  Dim str
  Do While Not StdIn.AtEndOfStream
    str = StdIn.ReadLine
    StdOut.WriteLine Ibm2Lat1(str)
  Loop

It is easy to see that other, similar conversion tasks can be done
with the same methods after just some slight customization.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:29 2008
Subject: 29) How do I drop the first two characters of a string, and so on?
Date: Thu,  6 Mar 2008 01:00:29
From: ts@uwasa.fi (Timo Salmi)

In CMD.EXE scripts dropping the first two characters is very simple:
  @echo off
  setlocal enableextensions
  set test_=This is a test
  echo %test_:~2%
  endlocal & goto :EOF
The output is
  is is a test

As we have seen, the base syntax for extracting a substring is
%var_:Start,Count% where the first character is designated 0 (zero)
not one. Thus
  @echo off
  setlocal enableextensions
  set test_=This_is_a_test
  echo %test_:~2,5%
  endlocal & goto :EOF
  echo %test_:~2,5%
gives
  is_is

Now, how about dropping the LAST two characters?
  @echo off
  setlocal enableextensions
  set test_=This_is_a_test
  echo %test_:~0,-2%
  endlocal & goto :EOF
gives
  This_is_a_te

Obviously there are more potential combinations, but this is how the
basics go.

References/Comments:
 http://www.google.com/groups?selm=c7d02vo2br8vmqtcagq7grttero4crnphd%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:30 2008
Subject: 30) Can one calculate the difference between two times in a script?
Date: Thu,  6 Mar 2008 01:00:30
From: ts@uwasa.fi (Timo Salmi)

Yes, one can:
  @echo off & setlocal enableextensions
  set /a diffSec=60*60*%4+60*%5+%6-(60*60*%1+60*%2+%3)
  if %diffSec% LSS 0 set /a diffSec=%diffSec%+24*60*60
  ::
  set /a h=(%diffSec%/3600)
  set /a m=(%diffSec%/60)-60*%h%
  set /a s=%diffSec%-60*(%diffSec%/60)
  ::
  echo hrs=%h% min=%m% sec=%s%
  ::
  endlocal & goto :EOF
For example
  D:\TEST>cmdfaq 12 13 56 17 4 57
  hrs=4 min=51 sec=1
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:31 2008
Subject: 31) How many days ago was 31.12.2002? What date it was 100 days ago?
Date: Thu,  6 Mar 2008 01:00:31
From: ts@uwasa.fi (Timo Salmi)

Days since a certain day can be calculated as follows. If the
current day is in the next year (2003) then the method effectively
gives today's annual day number.
  @echo off & setlocal enableextensions
  ::
  :: Get and show today's Julian date number
  :: Requires DATE2NUM.EXE from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
  DATE2NUM /set > "%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  set dateNumberNow=%datenum_%
  echo dateNumberNow=%dateNumberNow%
  ::
  :: Get and show the Julian date number of 31.12.2002
  DATE2NUM 31 12 2002 /set > "%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  set dateNumberThen=%datenum_%
  echo dateNumberThen=%dateNumberThen%
  ::
  :: Calculate the difference and show
  set /a ago_=%dateNumberNow% - %dateNumberThen%
  echo.
  echo 31.12.2002 was %ago_% days ago
  endlocal & goto :EOF

A screen capture could be something like
  D:\TEST>date /t
  08.12.2003

  D:\TEST>cmdfaq
  dateNumberNow=2452982
  dateNumberThen=2452640
  31.12.2002 was 342 days ago

Note how this item opens the door for calculating how old a file is
based on its datetime stamp.

Next a solution to the 100 days ago problem:
  @echo off & setlocal enableextensions
  ::
  :: Get and show today's Julian date number
  :: Requires DATE2NUM.EXE from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
  DATE2NUM /set > "%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  set dateNumberNow=%datenum_%
  echo dateNumberNow=%dateNumberNow%
  ::
  :: Subtract a hundred days
  set /a dateNumberThen=%dateNumberNow%-100
  echo dateNumberThen=%dateNumberThen%
  ::
  :: Convert it back into a date
  :: Requires NUM2DATE.EXE from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
  NUM2DATE %dateNumberThen% /set > "%mytemp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%mytemp%\tmp$$$.cmd"
  echo It was %ddpad_%.%mmpad_%.%yyyy_%
  endlocal & goto :EOF

The output would be something like
  D:\TEST>cmdfaq
  dateNumberNow=2452982
  dateNumberThen=2452882
  It was 30.08.2003

A Visual Basic Script (VBScript) aided command line script solution
option:
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%temp%\tmp$$$.vbs">"%temp%\tmp$$$.cmd"
  :: Call the command line script which the script host built
  call "%temp%\tmp$$$.cmd"
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
  :: Demonstrate the result
  echo dtoday_=%dtoday_%
  echo ago100_=%ago100_%
  echo fut100_=%fut100_%
  endlocal & goto :EOF
  '
  DateNow=Date                                    'VBS
  wscript.echo "@set dtoday_=" & Int(DateNow)     'VBS
  wscript.echo "@set ago100_=" & Int(DateNow-100) 'VBS
  wscript.echo "@set fut100_=" & Int(DateNow+100) 'VBS
The output might be something like
  D:\TEST>cmdfaq
  dtoday_=19.02.2005
  ago100_=11.11.2004
  fut100_=30.05.2005

Note how this item opens the door for identifying files which have
been made a given number of days ago. Or identifying how old a file
is. The latter task is solved in FILEAGE.CMD included in tscmd.zip.

One usage of the results of this item is constructing an XCOPY
parameter. In XCOPY /D:date "Copies files changed on or after the
specified date". E.g. for the previous thirty days you could have
  set xcdate_=%mmpad_%-%ddpad_%-%yyyy_%
  echo xcdate_=%xcdate_%
The needed exact XCOPY date format is dependent on your "Regional
Settings".

A VBS example with yesterday's date
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%temp%\tmp$$$.vbs">"%temp%\tmp$$$.cmd"
  :: Call the command line script which the script host built
  call "%temp%\tmp$$$.cmd"
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
  :: Demonstrate the result
  echo %date%
  echo ddpad_=%ddpad_%
  echo mmpad_=%mmpad_%
  echo yyyy_=%yyyy_%
  endlocal & goto :EOF
  '
  DateNow=Date                                     'VBS
  Yesterday=CStr(Int(DateNow-1))                   'VBS
  wscript.echo "@set ddpad_=" & Mid(Yesterday,1,2) 'VBS
  wscript.echo "@set mmpad_=" & Mid(Yesterday,4,2) 'VBS
  wscript.echo "@set yyyy_="  & Mid(Yesterday,7,4) 'VBS
The output might be for example
  D:\TEST>cmdfaq
  19.02.2005
  ddpad_=18
  mmpad_=02
  yyyy_=2005

The problems can also be solved with original script commands only.
To get "How many days ago was 31.12.2002". Local DD.MM.YYYY date
format is assumed.
  @echo off & setlocal enableextensions
  if "%~3"=="" (
    echo Usage: %~0 DD MM YYYY
    echo No leading zeros!
    goto :EOF)
  ::
  :: Get today's date elements
  for /f "tokens=1-3 delims=./-" %%f in ('date /t') do (
    set today_=%%h%%g%%f
    set dd_=%%f
    set mm_=%%g
    set yyyy_=%%h)
  :: Omit the leading zeros and trailing spaces
  for /f "tokens=* delims=0" %%a in ('echo %dd_%') do set dd_=%%a
  for /f "tokens=* delims=0" %%a in ('echo %mm_%') do set mm_=%%a
  set yyyy_=%yyyy_:~0,4%
  ::
  :: Get the second date
  set day=%~1
  set month=%~2
  set year=%~3
  ::
  :: Get the Julian day numbers and calculate the difference
  call :JDnumber %dd_% %mm_% %yyyy_% jd1_
  call :JDnumber %day% %month% %year% jd2_
  set /a diff_=%jd1_%-%jd2_%
  ::
  :: Display the result
  echo %dd_%.%mm_%.%yyyy_%
  echo %day%.%month%.%year%
  echo Julian day numbers %jd1_% %jd2_% Difference: %diff_% days
  endlocal & goto :EOF
  ::
  :: =========================================================
  :: Subroutine: Calculate the chronological Julian Day number
  :JDnumber day month year return_
  setlocal enableextensions
  set /a a=(14-%2)/12
  set /a y=%3+4800-%a%
  set /a m=%2+12*%a%-3
  set /a return_=%1+(153*%m%+2)/5+%y%*365+%y%/4-%y%/100+%y%/400-32045
  endlocal & set "%4=%return_%" & goto :EOF
The output might be e.g.
  C:\_D\TEST>cmdfaq 31 12 2005
  7.9.2006
  31.12.2002
  Julian day numbers 2453986 2452640 Difference: 1346 days

To get "What date it was 100 days ago?" with original script
commands only: (Also see DATEINFO.CMD)
  @echo off & setlocal enableextensions
  if "%~1"=="" (
    echo Usage: %~0 DaysAgo
    goto :EOF)
  ::
  :: Get today's date elements
  for /f "tokens=1-3 delims=./-" %%f in ('date /t') do (
    set today_=%%h%%g%%f
    set dd_=%%f
    set mm_=%%g
    set yyyy_=%%h)
  :: Omit the leading zeros and trailing spaces
  for /f "tokens=* delims=0" %%a in ('echo %dd_%') do set dd_=%%a
  for /f "tokens=* delims=0" %%a in ('echo %mm_%') do set mm_=%%a
  set yyyy_=%yyyy_:~0,4%
  ::
  :: How many days back
  set daysAgo=%~1
  ::
  :: Get today's Julian day number
  call :JDnumber %dd_% %mm_% %yyyy_% dateNumberNow
  ::
  :: Subtract the given number of days
  set /a dateNumberThen=%dateNumberNow%-%daysAgo%
  ::
  :: What was the date back then
  call :JDinverse %dateNumberThen% day month year
  ::
  :: Display the result
  echo dateNumberNow =%dateNumberNow%  for %dd_%.%mm_%.%yyyy_%
  echo dateNumberThen=%dateNumberThen%  for %daysAgo% days ago
  echo %day%.%month%.%year%
  endlocal & goto :EOF
  ::
  :: =========================================================
  :: Subroutine: Calculate the chronological Julian Day number
  :JDnumber day month year return_
  setlocal enableextensions
  set /a a=(14-%2)/12
  set /a y=%3+4800-%a%
  set /a m=%2+12*%a%-3
  set /a return_=%1+(153*%m%+2)/5+%y%*365+%y%/4-%y%/100+%y%/400-32045
  endlocal & set "%4=%return_%" & goto :EOF
  ::
  :: ===============================================
  :: Subroutine: Get the date of a Julian Day number
  :JDinverse dateNumber day month year
  setlocal enableextensions
  set /a a=%1+32044
  set /a b=(4*%a%+3)/146097
  set /a c=%a%-(%b%*146097)/4
  set /a d=(4*%c%+3)/1461
  set /a e=%c%-(1461*%d%)/4
  set /a m=(5*%e%+2)/153
  set /a day=%e%-(153*%m%+2)/5+1
  set /a month=%m%+3-12*(%m%/10)
  set /a year=%b%*100+%d%-4800+%m%/10
  endlocal &set "%2=%day%" &set "%3=%month%" &set "%4=%year%" &goto :EOF
The output might be e.g.
  C:\_D\TEST>cmdfaq 100
  dateNumberNow =2453986  for 7.9.2006
  dateNumberThen=2453886  for 100 days ago
  30.5.2006

References/Comments:
 http://www.google.com/groups?selm=nrwFWmAneiDCFwNY%40merlyn.demon.co.uk
 http://www.google.com/groups?selm=h0e0xpLhrfcDFwBK%40merlyn.demon.co.uk
 http://www.tondering.dk/claus/cal/node3.html#SECTION003161000000000000000
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:32 2008
Subject: 32) How can I convert a decimal number to binary, octal, hexadecimal?
Date: Thu,  6 Mar 2008 01:00:32
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  set decimal_=78
  call :DecimalToBinary %decimal_% binary_
  echo Decimal %decimal_% = Binary %binary_%
  ::
  call :DecimalToOctal %decimal_% oct_
  echo Decimal %decimal_% = Octal %oct_%
  ::
  call :DecimalToHex %decimal_% hex_
  echo Decimal %decimal_% = Hexadecimal %hex_%
  endlocal & goto :EOF

  ::===============================================================
  :DecimalToBinary DecimalIn BinaryOut
  ::
  setlocal enableextensions
  set /a dec_=%1
  if %dec_% LSS 0 (endlocal & set %2=Error: negative & goto :EOF)
  set bin_=
  :_binloop
    set /a dec1_=%dec_%
    set /a dec_=%dec_% / 2
    set /a bindigit_=%dec1_% - 2*%dec_%
    set bin_=%bindigit_%%bin_%
    if %dec_% GTR 0 goto :_binloop
  endlocal & set %2=%bin_% & goto :EOF

  ::===============================================================
  :DecimalToOctal DecimalIn OctalOut
  ::
  setlocal enableextensions
  set /a dec_=%1
  if %dec_% LSS 0 (endlocal & set %2=Error: negative & goto :EOF)
  set oct_=
  :_octloop
    set /a dec1_=%dec_%
    set /a dec_=%dec_% / 8
    set /a octdigit_=%dec1_% - 8*%dec_%
    set oct_=%octdigit_%%oct_%
    if %dec_% GTR 0 goto :_octloop
  endlocal & set %2=%oct_% & goto :EOF

  ::===============================================================
  :DecimalToHex DecimalIn HexOut
  ::
  setlocal enableextensions
  set /a dec_=%1
  if %dec_% LSS 0 (endlocal & set %2=Error: negative & goto :EOF)
  set hex_=
  :_hexloop
    set /a dec1_=%dec_%
    set /a dec_=%dec_% / 16
    set /a hexdigit_=%dec1_% - 16*%dec_%
    set /a hexidx_=%hexdigit_%+1
    for /f "tokens=%hexidx_%" %%h in (
      'echo 0 1 2 3 4 5 6 7 8 9 A B C D E F') do set hexdigit_=%%h
    set hex_=%hexdigit_%%hex_%
    if %dec_% GTR 0 goto :_hexloop
  endlocal & set %2=%hex_% & goto :EOF

The output will be
  D:\TEST>cmdfaq
  Decimal 78 = Binary 1001110
  Decimal 78 = Octal 116
  Decimal 78 = Hexadecimal 4E
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:33 2008
Subject: 33) How can I convert a binary, octal, hexadecimal into a decimal?
Date: Thu,  6 Mar 2008 01:00:33
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  set bin_=1001110
  call :BinToDecimal %bin_% decimal_
  echo Binary %bin_% = decimal %decimal_%
  ::
  set oct_=116
  call :OctToDecimal %oct_% decimal_
  echo Octal %oct_% = decimal %decimal_%
  ::
  set hex_=4E
  call :HexToDecimal %hex_% decimal_
  echo Hexadecimal %hex_% = decimal %decimal_%
  endlocal & goto :EOF

  ::===============================================================
  :BinToDecimal BinaryIn DecimalOut
  ::
  setlocal enableextensions
  set bin_=%1
  set /a dec_=0
  :_loop
    set first_=%bin_:~0,1%
    set /a dec_=%first_%+2*%dec_%
    set bin_=%bin_:~1%
    if defined bin_ goto _loop
  endlocal & set %2=%dec_% & goto :EOF

  ::===============================================================
  :OctToDecimal OctIn DecimalOut
  ::
  setlocal enableextensions
  set /a oct_=0%1
  endlocal & set %2=%oct_% & goto :EOF

  ::===============================================================
  :HexToDecimal HexIn DecimalOut
  ::
  setlocal enableextensions
  set /a hex_=0x%1
  endlocal & set %2=%hex_% & goto :EOF

The output will be
  D:\TEST>cmdfaq
  Binary 1001110 = decimal 78
  Octal 116 = decimal 78
  Hexadecimal 4E = decimal 78

A true application which I needed:
  @echo off & setlocal enableextensions
  ::
  :: Requires a parameter (in hexadecimal)
  if [%1]==[] goto _usage
  ::
  :: Put the parameter into a regular environment variable
  set hex_=%1
  ::
  :: The require format of the parameter is #C1C2C2
  :: Where C1 is the first color in hexadecomal and so on
  set h0_=%hex_:~0,1%
  if not [%h0_%]==[#] goto _usage
  ::
  :: Check that the parameter is not too long
  set h4_=%hex_:~7,1%
  if defined h4_ goto _usage
  ::
  :: Decompose the parameter into three parts with two characters each
  set h1_=%hex_:~1,2%
  set h2_=%hex_:~3,2%
  set h3_=%hex_:~5,2%
  ::
  :: Convert the hexadecimals
  set /a d1_=0x%h1_%
  set /a d2_=0x%h2_%
  set /a d3_=0x%h3_%
  ::
  :: Display the results
  echo %h1_% %h2_% %h3_%
  echo %d1_% %d2_% %d3_%
  goto :EOF
  ::
  :_usage
  echo +----------------------------------------------------+
  echo ^| Covert a hexadecimal color code into decimal       ^|
  echo ^| By Prof. Timo Salmi, Last modified Fri 29-Apr-2005 ^|
  echo +----------------------------------------------------+
  echo.
  echo Usage %~f0 #C1C2C3
  echo.
  echo Where C1 is the first color in hexadecimal and so on
  goto :EOF
The output might be
  C:\_D\TEST>cmdfaq #ff1faa
  ff 1f aa
  255 31 170

If one wants a better error handling, substitute
  ::
  :: Convert the hexadecimals, check the hex input for validity
  set /a d1_=0x%h1_% || (
    echo. & echo Invalid hexadecimal %h1_% in %hex_% & goto :EOF)
  set /a d2_=0x%h2_% || (
    echo. & echo Invalid hexadecimal %h2_% in %hex_%
    goto :EOF)
  set /a d3_=0x%h3_% || (
    echo.
    echo Invalid hexadecimal %h3_% in %hex_%
    goto :EOF)
Note at the same time the demonstrations of different formats. For
more on the conditional processing symbol || see
 hh ntcmds.chm::/ntcmds_shelloverview.htm

References/Comments:
 http://www.google.com/groups?selm=42722b29%240%248298%245a62ac22%40per-qv1-newsreader-01.iinet.net.au
 http://www.google.com/groups?selm=42732693%240%2483065%24ed2619ec%40ptn-nntp-reader01.plus.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:34 2008
Subject: 34) How can I remove the quote characters from a line?
Date: Thu,  6 Mar 2008 01:00:34
From: ts@uwasa.fi (Timo Salmi)

Below is a demonstration
  @echo off & setlocal enableextensions
  ::
  :: Set up a test
  set line_="54321","1","3","1234567890122","","","","","",""
  echo %line_%
  ::
  :: Omit the quotes
  set line_=%line_:"=%
  ::
  :: List the first four fields
  for /f "tokens=1-4 delims=," %%f in ('echo %line_%') do (
    call :ListThem %%f %%g %%h %%i)
  endlocal & goto :EOF
  :: ======================================================
  :ListThem
  setlocal enableextensions
    echo.%1
    echo.%2
    echo.%3
    echo.%4
  endlocal & goto :EOF

The output will be
  D:\TEST>batfaq
  "54321","1","1","1234567890122","","","","","",""
  54321
  1
  3
  1234567890122
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:35 2008
Subject: 35) How can I substitute the second field on each line of my file?
Date: Thu,  6 Mar 2008 01:00:35
From: ts@uwasa.fi (Timo Salmi)

Below is a simple demonstration substituting the second field with
"ab" on all the lines. Note the formulation of the for tokens, so
that all the fields will be covered.

  @echo off
  echo "123","45","678","901","234"> myfile.txt
  echo "234","56","789","012","345">>myfile.txt

  @echo off & setlocal enableextensions
  for /f "tokens=1,3,* delims=," %%q in ('type myfile.txt') do (
    echo %%q,"ab",%%r,%%s>>outfile.txt)
  type outfile.txt
  endlocal & goto :EOF

The output will be
  F:\CMD>d:cmdfaq
  "123","ab","678","901","234"
  "234","ab","789","012","345"

Note that the method will work even if the format of the lines were
"123" , "45" , "678" , "901" ,  "234"
For removing the quotes (if need be) and extracting separately the
contents of each field, see the previous item.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:36 2008
Subject: 36) I start a program from my script and it hogs my command window.
Date: Thu,  6 Mar 2008 01:00:36
From: ts@uwasa.fi (Timo Salmi)

Occasionally one may want to call a program from the command line
window. Furthermore, it sometimes is useful to build calling that
program into a script e.g. for customization. However, when one
does, the command window will "freeze" to wait for the completion of
the task. How can one avoid that and free the command window for
other parallel usages? The trick is to start the program using the
START internal command.

As an example, my favorite text editor is the SemWare Editor
Professional. Below is one of the options of how I may call it. It
is a batch/script that is meant to work on both my 95 and my XP PC.
This means that in Windows95 it must not have to encounter for it
unknown (CMD.EXE) lines of the batch/script.

  @echo off
  :: E.BAT by Prof. Timo Salmi
  :: One option for calling the SemWare Editor Professional
  ::
  if [%OS%]==[Windows_NT] goto _nt
  if [%1]==[] L:\TSEPro\e32 *.*
  if not [%1]==[] L:\TSEPro\e32 %1 %2 %3 %4 %5 %6 %7
  goto _out
  ::
  :_nt
  if [%1]==[] (
    start "" "C:\Program Files\TSEPro\e32" *.*
      ) else (
    start "" "C:\Program Files\TSEPro\e32" %1 %2 %3 %4 %5 %6 %7)
  ::
  :_out

References/Comments:
 http://www.google.com/groups?selm=vua9ifpaqeqi92%40corp.supernews.com
 http://www.google.com/groups?selm=rf8jprwem3va.1jkl9tq5cj629%24.dlg%4040tude.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:37 2008
Subject: 37) How can I insert a line in the middle of a file with a script?
Date: Thu,  6 Mar 2008 01:00:37
From: ts@uwasa.fi (Timo Salmi)

This is easy with the additional tools SED or GAWK. Say that you wish
to insert something between the fourth and the fifth line of your
file. Below is how to do it:

  @echo off
  sed -n 1,4p myfile.txt>newfile.txt
  echo Insert My added own line>>newfile.txt
  sed -n 5,$p myfile.txt>>newfile.txt

With G(nu)AWK the solution is even simpler
  gawk '{print;if(NR==4)print"My own added line"}' myfile.txt>newfile.txt

However, this can also be solved with pure script. The solution
below using subroutines is not the most concise one, but hopefully
it is instructive. In a FAQ like this clarity is preferred over
conciseness and sometimes even efficiency. Also note how as a
sideline it answers the questions "How do I get the first N lines of
my text file?" and "How do I get my text file's lines after line N".
(The latter could be answered with "skip=" as well.)

  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt mynew.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>myfile.txt
  ::
  :: Insert where
  set insertAfter=4
  ::
  :: Initialize the linecount
  set /a lineCount=0
  ::
  :: Write the lines until and including the insertion point
  for /f "delims=" %%r in ('type myfile.txt') do (
    call :WriteUntilLine %%r>>mynew.txt
    )
  ::
  :: Insert new text
  echo My added text>>mynew.txt
  ::
  :: Start a new count
  set /a lineCount=0
  ::
  :: Write the lines until and including the insertion point
  for /f "delims=" %%r in ('type myfile.txt') do (
    call :WriteSinceLine %%r>>mynew.txt
    )
  ::
  :: Display the new file
  type mynew.txt
  ::
  :: Clean up
  for %%f in (myfile.txt mynew.txt) do if exist %%f del %%f
  endlocal & goto :EOF

  :: ======================================================
  :WriteUntilLine
  set /a lineCount+=1
  if %lineCount% LEQ %insertAfter% echo %*
  goto :EOF

  :: ======================================================
  :WriteSinceLine
  set /a lineCount+=1
  if %lineCount% GTR %insertAfter% echo %*
  goto :EOF

The output
  D:\TEST>cmdfaq
  This is line 1
  This is line 2
  This is line 3
  This is line 4
  My own added line
  This is line 5
  This is line 6
  This is line 7
  This is line 8
  This is line 9

For a more concise, and also instructive alternative see
http://www.google.com/groups?selm=brrnkc%246ou2e%241%40ID-55492.news.uni-berlin.de

For replacing a line instead of inserting, substitute
  if %lineCount% LEQ %insertAfter% echo %*
with
  if %lineCount% LSS %insertAfter% echo %*
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:38 2008
Subject: 38) How can I set and test the errorlevel within a script file?
Date: Thu,  6 Mar 2008 01:00:38
From: ts@uwasa.fi (Timo Salmi)

EXIT can be used to set the errorlevel. Note the ^2 to avoid it from
being mistaken for a handle.
  @echo off & setlocal enableextensions
  echo.@exit /B ^2>tmp$$$.cmd
  call tmp$$$
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  echo Bye from %0 on %date% at %time%
  for %%f in (tmp$$$.cmd) do if exist %%f del %%f
  goto :EOF
The output will be something like
  D:\TEST>cmdfaq
  The errorlevel is 2
  By from cmdfaq on 19.12.2003 at  8:18:03.21

Another alternative is to utilise gawk:
  @echo off & setlocal enableextensions
  :: Requires G(nu)AWK
  gawk 'BEGIN{exit 2}'
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  echo Bye from %0 on %date% at %time%
  goto :EOF
The output will be something like
  F:\CMD>d:\test\cmdfaq
  The errorlevel is 2
  By from d:\test\cmdfaq on 19.12.2003 at  8:19:08.69

A wider scale for testing the errorlevel. Note that the errorlevel
must be stored before the next SET because also SET sets the
errorlevel.
  @echo off & setlocal enableextensions enabledelayedexpansion
  echo.@exit /B ^5>"%temp%\tmp$$$.cmd"
  call "%temp%\tmp$$$"
  set errorlev_=%errorlevel%
  set /a e_=0
  :_loop
    if !errorlev_! EQU %e_% (
      echo The errorlevel is %e_%
      ) else (
      set /a e_+=1
      if %e_% LEQ 255 goto _loop)
  for %%f in ("%temp%\tmp$$$.cmd") do if exist %%f del %%f
  goto :EOF

With Visual Basic Script one can have
  @echo off & setlocal enableextensions
  :: Make a temporary folder
  if not exist c:\mytemp mkdir c:\mytemp
  ::
  :: Set the errorlevel
  echo WScript.Quit ^5>c:\mytemp\tmp$$$.vbs
  cscript //nologo c:\mytemp\tmp$$$.vbs
  ::
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  The errorlevel is 5

Actually, an XP srcipt can return an errorlevel without any
additional tricks as demonstrated below
  @echo off & setlocal enableextensions
  set cmdfile_="temp $$$.cmd"
  echo @exit /b ^2>%cmdfile_%
  call %cmdfile_%
  for %%e in (0 1 2 3 4 5 6 7 8 9) do (
    if %errorlevel% EQU %%e echo The errorlevel is %%e)
  for %%f in (%cmdfile_%) do if exist %%f del %%f
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  The errorlevel is 2

References/Comments:
 http://www.google.com/groups?selm=bs4nl5%249co%2404%241%40news.t-online.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:39 2008
Subject: 39) Is there a subroutine to convert a variable into uppercase?
Date: Thu,  6 Mar 2008 01:00:39
From: ts@uwasa.fi (Timo Salmi)

As below. Note that the substitution method is case insensitive,
which means that while working for this application, it is not
useful for all character substitution tasks. Also note the minor
detail of the Scandinavian character conversion.

  @echo off & setlocal enableextensions
  set myvar_=My Test String 
  call :ToUpcase "%myvar_%" myvar_
  echo %myvar_%
  endlocal & goto :EOF

  :: ======================
  :ToUpcase
  setlocal enableextensions
  set var_=%1
  set var_=%var_:a=A%
  set var_=%var_:b=B%
  set var_=%var_:c=C%
  set var_=%var_:d=D%
  set var_=%var_:e=E%
  set var_=%var_:f=F%
  set var_=%var_:g=G%
  set var_=%var_:h=H%
  set var_=%var_:i=I%
  set var_=%var_:j=J%
  set var_=%var_:k=K%
  set var_=%var_:l=L%
  set var_=%var_:m=M%
  set var_=%var_:n=N%
  set var_=%var_:o=O%
  set var_=%var_:p=P%
  set var_=%var_:q=Q%
  set var_=%var_:r=R%
  set var_=%var_:s=S%
  set var_=%var_:t=T%
  set var_=%var_:u=U%
  set var_=%var_:v=V%
  set var_=%var_:w=W%
  set var_=%var_:x=X%
  set var_=%var_:y=Y%
  set var_=%var_:z=Z%
  set var_=%var_:=%
  set var_=%var_:=%
  set var_=%var_:=%
  set var_=%var_:"=%
  endlocal & set %2=%var_%& goto :EOF

The output is
  F:\CMD>d:cmdfaq
  MY TEST STRING 

More concisely, one can capitalize (if you pardon the pun) on the
fact that in for and the substitution lower and upper case source
are equivalent.
  @echo off & setlocal enableextensions enabledelayedexpansion
  set myvar_=My Test String  
  echo %myvar_%
  call :ToUpcase "%myvar_%" myvar_
  echo %myvar_%
  endlocal & goto :EOF
  ::
  :: ======================
  :ToUpcase
  setlocal enableextensions
  set var_=%~1
  for %%c in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z   ) do (
    set var_=!var_:%%c=%%c!
    )
  endlocal & set %2=%var_%& goto :EOF

Another option is
  @echo off & setlocal enableextensions
  set myvar_=My Test String 
  call :ToUpcase "%myvar_%" myvar_
  echo %myvar_%
  endlocal & goto :EOF

  :: ================================================================
  :ToUpcase
  :: Requires G(nu)AWK
  setlocal enableextensions
  gawk 'BEGIN{printf"@set var_=%%s\n",toupper(%1)}'>"%temp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%temp%\tmp$$$.cmd"
  endlocal & set %2=%var_% & goto :EOF

The output is slightly different
  F:\CMD>d:cmdfaq
  MY TEST STRING 

Another script-only method. More complicated, but on the side
demonstrates several features of cmd script programming.
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Constants for the lower and upper case
  set dn=abcdefghijklmnopqrstuvwxyz
  set up=ABCDEFGHIJKLMNOPQRSTUVWXYZ
  ::
  :: Set a test string
  if "%~1"=="" (
    set Str=This is a test string
    ) else (
    set Str=%*
    )
  ::
  :: Get the length of the string assuming a max of 255
  set charCount=0
  for /l %%i in (0,1,254) do (
    set char=!Str:~%%i,1!
    if defined char set /a charCount+=1)
  ::
  :: Upcase character by character
  set StrUp=
  for /l %%i in (0,1,%charCount%) do (
    set char=!Str:~%%i,1!
    for /l %%p in (0,1,28) do (
      if [!char!]==[!dn:~%%p^,1!] set char=!up:~%%p,1!
      )
    set StrUp=!StrUp!!char!
    )
  ::
  :: Display the result
  echo %Str%
  echo %StrUp%
  endlocal & goto :EOF
An example of the output
  C:\_D\TEST>cmdfaq Hello World
  Hello World
  HELLO WORLD

There are other options. Using SED we can have
  @echo off & setlocal enableextensions
  set myvar_=My Test String 
  call :ToUpcase "%myvar_%" myvar_
  echo %myvar_%
  endlocal & goto :EOF

  :: ====================================================================
  :ToUpcase
  :: Requires SED
  setlocal enableextensions
  for /f "tokens=*" %%f in ("%temp%") do set temp_=%%~sf
  echo @set var_=%1|sed "y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/"|sed -e "s/\"//g">%temp_%\tmp$$$.cmd
  for %%c in (call del) do %%c %temp_%\tmp$$$.cmd
  endlocal & set %2=%var_% & goto :EOF

The output is back to
  F:\CMD>d:cmdfaq
  MY TEST STRING 

The conversion can also be done with a Visual Basic Script
(VBScript) aided command line script
  @echo off & setlocal enableextensions
  ::
  :: The text to be concerved to upper case
  set MyText_=Scripts are fun, or are they?
  ::
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo tmp$$$.vbs
  :: Call the command line script wchich the script host built
  call tmp$$$.cmd
  :: Clean up
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  ::
  :: Demonstrate the result
  echo %MyText_%
  echo %MyTextUp_%
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  Dim MyString, MyStringUp                                                'VBS
  Set WshShell = WScript.CreateObject("WScript.shell")                    'VBS
  MyString=WshShell.ExpandEnvironmentStrings("%MyText_%")                 'VBS
  MyStringUp = UCase(MyString)                                            'VBS
  WshShell.run "cmd /c echo @set MyTextUp_=" & MyStringUp & ">tmp$$$.cmd" 'VBS

References/Comments:
 http://www.google.com/groups?selm=bs12o7%248fgvr%241%40ID-55492.news.uni-berlin.de
 http://www.google.com/groups?selm=bs2ald%248oc84%241%40ID-55492.news.uni-berlin.de
Also see ftp://garbo.uwasa.fi/pc/link/tsbat.zip item #7
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:40 2008
Subject: 40) How do I get the number of arguments given to a script?
Date: Thu,  6 Mar 2008 01:00:40
From: ts@uwasa.fi (Timo Salmi)

This task is not quite as trivial as it first appears to be. There
are a couple of subtle pitfalls. Since the solution uses shift it
"destroys" the parameters from later usage, so they have to be
stored. The logic is that if one wants to count the parameters, one
is likely also to want to use the parameters! Also note the usage of
[] in the if testing lest there is confusion with parameters
potentially enclosed in quotes. If one needs a parameter count, it
is logical and sensible to always put it as the first thing into the
script. The denotations in the example below have clear UNIX
connotations.

Take one:
========

  @echo off & setlocal enableextensions enabledelayedexpansion
  set /a argc=0
  :_argcLoop
    if [%1]==[] goto _exitargcLoop
    set /a argc+=1
    set arg%argc%=%1
    shift
    goto _argcLoop
  :_exitargcLoop
  ::
  :: Show the results
  echo The number of parameters is %argc%
  set /a count_=0
  :_dispLoop
    set /a count_+=1
    if defined arg%count_% (echo !arg%count_%! & goto _dispLoop)
  ::
  endlocal & goto :EOF

An example:
  D:\TEST>cmdfaq one two "the third"
  The number of parameters is 3
  one
  two
  "the third"

If you wish to omit the quotes (") substitute
  set arg%argc%=%~1

Take two:
========

  @echo off & setlocal enableextensions enabledelayedexpansion
  set argc=0
  :_loop
    if "%~1"=="" goto _next
    set /a argc+=1
    set argv[!argc!]=%~1
    shift
    goto _loop
  :_next
  ::
  echo argc=%argc%
  for /l %%i in (1,1,%argc%) do echo argv[%%i]=!argv[%%i]!
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq a  b c "d e"
  argc=4
  argv[1]=a
  argv[2]=b
  argv[3]=c
  argv[4]=d e

Note a catch. After you apply the above, you no longer can access
the original parameters. If you need them later in the batch, you
have to store them at the outset of the batch file like in the above.

Let's consider a more complicated extraction of command line
information:
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: The task:
  :: Get switches and ordinary parameters given to a script.
  :: Distinguish between the two categories
  ::
  set argc=0
  :_loop
    if "%~1"=="" goto _next
    set /a argc+=1
    set argv[!argc!]=%~1
    shift
    goto _loop
  :_next
  ::
  echo argc=%argc%
  for /l %%i in (1,1,%argc%) do echo argv[%%i]=!argv[%%i]!
  ::
  set paramCount=0
  set switchCount=0
  for /l %%i in (1,1,%argc%) do (
    echo.!argv[%%i]!| find "/">nul
    if !errorlevel! EQU 0 (
      set /a switchCount+=1
      set switch[!switchCount!]=!argv[%%i]!
      ) else (
      set /a paramCount+=1
      set param[!paramCount!]=!argv[%%i]!
      )
    )
  ::
  echo switchCount=%switchCount%
  echo paramCount=%paramCount%
  for /l %%i in (1,1,%switchCount%) do (
    echo swithch[%%i]=!switch[%%i]!)
  for /l %%i in (1,1,%paramCount%) do (
    echo param[%%i]=!param[%%i]!)
  endlocal & goto :EOF
The output might be e.g.
  C:\_D\TEST>cmdfaq a /b /c "Hello World" /?
  argc=5
  argv[1]=a
  argv[2]=/b
  argv[3]=/c
  argv[4]=Hello World
  argv[5]=/?
  switchCount=3
  paramCount=2
  swithch[1]=/b
  swithch[2]=/c
  swithch[3]=/?
  param[1]=a
  param[2]=Hello World

Take three:
==========

Let's drop the switch handing but add how to get the parameters so
that also the poison characters can be handled. At the same time the
code is much streamlined. Note the trick to use the call. Also, no
shift.

  @echo off & setlocal enableextensions disabledelayedexpansion
  set n=0
  for %%a in (%*) do (set /a n+=1)&(call set p[%%n%%]=%%a)
  ::
  echo n=%n%
  for /L %%i in (1,1,9) do if defined p[%%i] call echo p[%%i]=%%p[%%i]%%
  for /L %%i in (2,1,9) do if defined p[%%i] call set rest_=%%rest_%% %%p[%%i]%%
  if defined rest_ set rest_=%rest_:~1%
  echo rest_=%rest_%
  endlocal & goto :EOF

An example of the output
  C:\_D\TEST>cmdfaq 1 2 3 "Hello World" "a & b"
  n=5
  p[1]=1
  p[2]=2
  p[3]=3
  p[4]="Hello World"
  p[5]="a & b"
  rest_=2 3 "Hello World" "a & b"

References/Comments:
 http://www.google.com/groups?selm=bs6li2%24bth%2404%241%40news.t-online.com
 http://www.google.com/groups?selm=Buvnc.404043%24Pk3.48231%40pd7tw1no
 http://www.google.com/groups?selm=mcg1bqF0MknAFwGV%40merlyn.demon.co.uk
 http://www.google.com/groups?selm=443e85ec%240%247489%249b536df3%40news.fv.fi
 http://www.google.com/groups?selm=nn8ks3d9l8k25c0b742or17cg38k3s8j6u%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:41 2008
Subject: 41) How can I create a zero-byte file? How do I test for it?
Date: Thu,  6 Mar 2008 01:00:41
From: ts@uwasa.fi (Timo Salmi)

  @echo off
  if exist testfile goto _nocreate    %Don't destroy an existing file%
  type nul>testfile
  :_nocreate

or
  @echo off
  if exist testfile goto _nocreate    %Don't destroy an existing file%
  echo off>testfile
  :_nocreate

Alternatively
  @echo off
  copy /-y nul testfile

To see one of the small but significant differences bewtween
NT/2000/XP and MS-DOS+Win../95/98/Me solutions compare the above
solution with item #42 of ftp://garbo.uwasa.fi/pc/link/tsbat.zip
In MS-DOS+Win../95/98/Me rem can used for trhe purpose, but not the
copy nul solution.

Another option. This time with a long name and also a file-size test
included.
  @echo off & setlocal enableextensions
  set testfile_="My test file"
  if exist %testfile_% goto _nocreate    %Don't destroy an existing file%
  copy nul %testfile_%>nul
  :_nocreate
  call :TestForZeroFile %testfile_% isZeroFile_
  echo %testfile_% is a zero-byte file = %isZeroFile_%
  endlocal & goto :EOF

  :: ====================================
  :TestForZeroFile
  setlocal enableextensions
  set file_=%1
  for %%f in (%file_%) do set size_=%%~zf
  set return_=false
  if %size_% EQU 0 set return_=true
  endlocal & set %2=%return_% & goto :EOF

Screeen captures:
  D:\TEST>cmdfaq
  "My test file" is a zero-byte file = true

  D:\TEST>dir | find "My"
  24.12.2003  09:56                 0 My test file

References/Comments:
 http://www.google.com/groups?selm=n1adn1dd8pc6l3hfksq2i8v0vusg3qgrnb%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:42 2008
Subject: 42) What is the subroutine for testing a filename for wildcards?
Date: Thu,  6 Mar 2008 01:00:42
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  :: Demo
  set filename_="My * file"
  call :IsWildSub %filename_% isWild
  if "%isWild%"=="yes" (
    echo %filename_% contains wildcards
    ) else (
    echo No wildcards in %filename_%)
  ::
  set filename_="My file"
  call :IsWildSub %filename_% isWild
  if "%isWild%"=="yes" (
    echo %filename_% contains wildcards
    ) else (
    echo No wildcards in %filename_%)
  endlocal & goto :EOF

  :: =====================================================
  :: Does a name contain wildcards * and/or ?
  :IsWildSub
  setlocal enableextensions
  echo %1|find "*">nul
  if %errorlevel% EQU 0 (endlocal & set %2=yes& goto :EOF)
  echo %1|find "?">nul
  if %errorlevel% EQU 0 (endlocal & set %2=yes& goto :EOF)
  endlocal & set %2=no& goto :EOF

The output
  D:\TEST>cmdfaq
  "My * file" contains wildcards
  No wildcards in "My file"

References/Comments:
 http://www.google.com/groups?selm=bsfh6p%244kn%40poiju.uwasa.fi

Based on the comment thread:
  @echo off & setlocal enableextensions
  set filename_="My * file"
  echo %filename_%|findstr "[*?]">nul
  if %errorlevel% EQU 0 (
    echo %filename_% contains wildcards
    ) else (
    echo No wildcards in %filename_%)
  endlocal & goto :EOF

Note that this also could be written as
  @echo off & setlocal enableextensions
  set filename_="My * file"
  echo %filename_%|findstr "[*?]">nul ^
    && echo %filename_% contains wildcards^
    || echo No wildcards in %filename_%
  endlocal & goto :EOF

The output would be
  C:\_D\TEST>cmdfaq
  "My * file" contains wildcards
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:43 2008
Subject: 43) Is there a way of counting the number of files in a folder?
Date: Thu,  6 Mar 2008 01:00:43
From: ts@uwasa.fi (Timo Salmi)

Let's actually count the number of files and subfolders instead of
trying to extract the information
  @echo off & setlocal enableextensions
  set /a countd_=0
  set /a countf_=0
  for /f %%f in ('dir /s /b /a:d d:\*.*') do set /a countd_+=1
  for /f %%f in ('dir /s /b /a:-d d:\*.*') do set /a countf_+=1
  echo Found %countf_% files, %countd_% folders
  endlocal & goto :EOF

The output might be e.g.
  D:\TEST>cmdfaq
  Found 1997 files, 122 folders

Let's not stop there, but list the files together with an ordinal
number. The possibility of long files names is taken into account.

  @echo off & setlocal enableextensions
  set /a FileCount_=0
  for /f "delims=" %%f in ('dir /s /b /a:-d /o:e f:\xtools\*.*') do (
    call :ListOneFile %%f)
  endlocal & goto :EOF

  :: ===========================================
  :ListOneFile
  set /a FileCount_+=1
  call :FuncRightJustify %FileCount_% FileCount_
  echo %FileCount_: =0% %*
  goto :EOF

  :: ===========================================
  :FuncRightJustify arg1 arg2
  setlocal enableextensions
  set number_=    %1
  set number_=%number_:~-5%
  endlocal & set "%2=%number_%" & Goto :EOF

The output might be something like
  D:\TEST>cmdfaq
  00001 f:\xtools\CLRBURN.CMD
  00002 f:\xtools\CLRM.CMD
  00003 f:\xtools\CLRTEMPL.CMD
  00004 f:\xtools\CMDBOX.CMD
  00005 f:\xtools\CONVMAIL.CMD
  00006 f:\xtools\XPTODAY.CMD
  00007 f:\xtools\HOMMAG.CMD
  00008 f:\xtools\M_TSCMD.CMD
  00009 f:\xtools\PGPWXP.CMD
  00010 f:\xtools\SHEZXP.CMD
  00011 f:\xtools\TEST.CMD
  00012 f:\xtools\TODAY2N.CMD
  00013 f:\xtools\VPP3DXP.CMD
  00014 f:\xtools\WHEREIS.CMD
  :
  00151 f:\xtools\My test file.txt
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:44 2008
Subject: 44) How do I get the first 68 columns from a text file?
Date: Thu,  6 Mar 2008 01:00:44
From: ts@uwasa.fi (Timo Salmi)

Actually, needed this one for my own tasks.
  @echo off & setlocal enableextensions
  set filename_=myfile.txt
  if not exist %filename_% (
    echo File %filename_% not found
    goto :EOF)
  if exist outfile.txt del outfile.txt
  for /f "delims=" %%r in ('type %filename_%') do call :WriteLine %%r
  dir outfile.txt
  endlocal & goto :EOF

  :: ============================
  :WriteLine
  setlocal enableextensions
  set line_=%*
  echo %line_:~0,68%>>outfile.txt
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:45 2008
Subject: 45) How can I find out how many days old a file is?
Date: Thu,  6 Mar 2008 01:00:45
From: ts@uwasa.fi (Timo Salmi)

The accompanying FILEAGE.CMD script has been written for that
purpose. An example of the output

  F:\CMD>echo %date%
  30.12.2003

  F:\CMD>fileage fileage.cmd
  +----------------------------------------------------+
  | FILEAGE.CMD script to find out how old a file is   |
  | By Prof. Timo Salmi, Last modified Sun 28-Dec-2003 |
  +----------------------------------------------------+

  28.12.2003 18:50 2324 F:\CMD\FILEAGE.CMD
  The file is 2 days old
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:46 2008
Subject: 46) Is a program available in the default folder or at path?
Date: Thu,  6 Mar 2008 01:00:46
From: ts@uwasa.fi (Timo Salmi)

A counterpart of the UNIX "which" command.
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  if [%1]==[] (
    echo Usage: %~0 [Filename]
    goto :EOF)
  ::
  if not [%2]==[] (
    echo Usage for long file names: %~0 ["Filename"]
    goto :EOF)
  ::
  set target_=%~1
  ::
  for %%f in ("%target_%") do set where_="%%~$PATH:f"
  if exist "%target_%" set where_="%cd%\%target_%"
  if [%where_%]==[""] (
    echo "%target_%" not found at path or current folder
    ) else (
    set where_=!where_:"=!
    echo where_=!where_!)
  ::
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=nbh5i1tglbr6o3vml87avvta7v2c99et59%404ax.com
 http://www.google.com/groups?selm=729hi11m33e4548s35rbhtli6hvlgesu4d%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:47 2008
Subject: 47) Is it possible to echo the redirection symbol in a script?
Date: Thu,  6 Mar 2008 01:00:47
From: ts@uwasa.fi (Timo Salmi)

There are several examples to that effect throughout the FAQ at hand.
Just search through this file for instances of the caret ^ escape
character.

It is not the only method, though, as reminded in
http://www.google.com/groups?selm=bsnpio%24eo2ml%241%40ID-55492.news.uni-berlin.de
The line below is an exact extract from that message:
  <nul (set /p z="<this>|<is>|<only>|<a>|<TEST>")>out.txt

A second option to produce the said text is
  for %%a in ("<this>|<is>|<only>|<a>|<TEST>") do echo %%~a
which also will give you
  <this>|<is>|<only>|<a>|<TEST>

The difference is that the first method will not produce a new line
while the second one will.

One way of producing any character is using G(nu)AWK. For example,
to produce the pound symbol () Hex 9C apply
  gawk "BEGIN{print \"\x9C\n\"}"

Also the methods presented in the MS-DOS+Win..95/98/ME FAQ item
 "38) Is it possible to echo the redirection symbol in a batch?"
 ftp://garbo.uwasa.fi/pc/link/tsbat.zip
should work. But these are just additional, complicated ways of
doing what is already covered by the ^ escape character.

Also consider the following example demonstrating a difference
between MS-DOS+Win../95/98/Me COMMAND.COM batches and NT/2000/XP
CMD.EXE scripts. The user wishes to echo the ampersand (&)
character. For the former neither the caret ^ nor the ampersand &
has a special meaning while for the latter they do. For CMD.EXE the
caret in the escape character and the ampersand &  the multiple
commands on one command line character. Thus given
  @echo off
  echo &
  echo ^&
MS-DOS+Win../95/98/Me will produce
  &
  ^&
while NT/2000/XP will produce
  ECHO is off.
  &
Hence for NT/2000/XP the solution is
  @echo off
  echo Echoing the ^& ampersand

The NT/2000/XP special characters which require escaping are
<space>&()[]{}^=;!'+,`~


A question from microsoft.public.win2000.cmdprompt.admin:
  I (Tom) am trying to have a BAT file generate another BAT file. In
  that target BAT file, I would like to write values like:

    CALL MyBatFile.bat %1 %2 > MyTargetOutputFile

  I tried executing the following command...

    echo "CALL MyBatFile.bat %1 %2 > MyTargetOutputFile" >> NewBatFile.bat

  Of course the %1 and %2 are getting substituted (I just want the
  literal values %1 and %2 written).  Furthermore the first > tries
  to pipe the output to MyTargetOutputFile (I also wanted ">
  MyTargetOutputFile" to be written to the NewBatFile.bat. Is there
  any way to do what I want?

The answer:
  echo CALL MyBatFile.bat %%1 %%2 ^> MyTargetOutputFile >> NewBatFile.bat

References/Comments:
 hh ntcmds.chm::/echo.htm
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:48 2008
Subject: 48) Why do some comment lines cause errors? What can I do about it?
Date: Thu,  6 Mar 2008 01:00:48
From: ts@uwasa.fi (Timo Salmi)

Consider the following script
  @echo off & setlocal enableextensions
  rem set var2=%~var1%
  echo We made it!
  endlocal & goto :EOF
While this should work (the second, syntactically incorrect line is
just a comment) the (slightly condensed) output will be
  D:\TEST>cmdfaq
  The following usage of the path operator in script-parameter
  substitution is invalid: %~var1%
  For valid formats type CALL /? or FOR /?
  The syntax of the command is incorrect.

Now why is this? I do not know. I can only speculate. It would
appear that a command line is paresed from the end towards the
beginning. If so, the error is reported before the REM comment
command is reached. That obviously is a bug in the Microsift
NT/2000/XP CMD.EXE command line processor parser.

The following alternatives cause the same error
  @echo off & setlocal enableextensions
  :: set var2=%~var1%
  echo We made it!
  endlocal & goto :EOF
and
  @echo off & setlocal enableextensions
  rem set var2=%~var1%> nul 2>&1
  echo We made it!
  endlocal & goto :EOF

What can one do about it? The only solution I currently know is an
ugly one:
  @echo off & setlocal enableextensions
  goto _afterComment
  rem set var2=%~var1%
  :_afterComment
  echo We made it!
  endlocal & goto :EOF
Now the output will be as it should:
  D:\TEST>cmdfaq
  We made it!

References/Comments:
 http://www.google.com/groups?selm=mzCeKqBCEF5%2BEwff%40ponle.demon.co.uk
 http://www.google.com/groups?selm=Ox1Jb.906684%249l5.799065%40pd7tw2no
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:49 2008
Subject: 49) I need to reverse a text file. How do I do that fairly quickly?
Date: Thu,  6 Mar 2008 01:00:49
From: ts@uwasa.fi (Timo Salmi)

This item benefits from a discussion in the news:alt.msdos.batch.nt
as per the earlier item #23. The code needed is relatively brief.
This also introduced the use of FOR /L for the first time in this
FAQ.

  @echo off & setlocal enableextensions
  :: Make a test file
  set fileName=mytest.txt
  for %%f in ("%fileName%" "%temp%\mytemp.txt") do if exist %%f del %%f
  for %%f in (1 2 3 4 5 6 7 8 9) do echo This is line %%f>>"%fileName%"
  ::
  :: Get the number of lines
  for /f %%a in ('find /v /c "" ^< "%fileName%"') do set /a lineCount=%%a
  ::
  :: Loop through the lines of the file from the last line to the first
  for /l %%a in (%lineCount%,-1,1) do call :OutputOneLine %%a
  ::
  :: Clean up
  for %%f in ("%fileName%" "%temp%\mytemp.txt") do if exist %%f del %%f
  endlocal & goto :EOF

  @echo off & setlocal enableextensions
  :: ============================================
  :OutputOneLine
  set /a StartAt = %1 - 1
  more /e +%StartAt% "%fileName%">"%temp%\mytemp.txt"
  set /p Nth_line=<"%temp%\mytemp.txt"
  echo %Nth_line%
  endlocal & goto :EOF

The output is
  D:\TEST>cmdfaq
  This is line 9
  This is line 8
  This is line 7
  This is line 6
  This is line 5
  This is line 4
  This is line 3
  This is line 2
  This is line 1

For GAWK and SED solutions see item #131 in
 ftp://garbo.uwasa.fi/pc/link/tsbat.zip

References/Comments:
 Feb 4  Matthias Tacke   Suggestion for Tscmd 049
 ftp://garbo.uwasa.fi/pc/pd2/tspost28.zip
 Information email + postings, from 19-Sep-00 to ...
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:50 2008
Subject: 50) How do I get the position of a substring in a string?
Date: Thu,  6 Mar 2008 01:00:50
From: ts@uwasa.fi (Timo Salmi)

One potential solution:
  @echo off & setlocal enableextensions
  rem    01234567890123456789
  set a_=Hello world, Hello.
  set b_=ll
  call :InstrFN "%a_%" "%b_%" position_
  echo The first position of "%b_%" in "%a_%" is %position_%
  endlocal & goto :EOF

  ::===============================================================
  :: A subroutine to find the first position of a searchstring in a
  :: mainstring. If not found returns -1. If found, the indexing of
  :: the position starts from 0 in accordance with SET conventions.
  ::
  :InstrFN
  setlocal enableextensions enabledelayedexpansion
  ::
  :: Get the mainstring and the searchstring, get rid of possible quotes
  set MainStr=%1
  set MainStr=%MainStr:"=%
  set SearchStr=%2
  set SearchStr=%SearchStr:"=%
  ::
  :: Get the length of the searchstring
  set rest_=%SearchStr%
  set /a SearchLength_=0
  :_length_loop
    set /a SearchLength_+=1
    set rest_=%rest_:~1%
    if defined rest_ goto :_length_loop
  ::
  :: Check for a non-match
  echo %MainStr%|find "%SearchStr%">nul
  if %errorlevel% EQU 1 (endlocal & set /a %3=-1& goto :EOF)
  ::
  :: Match the searchstring with mainstring substrings
  set /a i_=0
  :_position_loop
    if "!MainStr:~%i_%,%SearchLength_%!"=="%SearchStr%" (
      endlocal & set /a %3=%i_%& goto :EOF)
    set /a i_+=1
    goto _position_loop
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  The first position of "ll" in "Hello world, Hello." is 2

There are other solution options:
  @echo off & setlocal enableextensions enabledelayedexpansion
  set a_=Hello world, Hello.
  set b_=ll
  set instr=-1
  for /l %%i in (0,1,255) do (
   set str=!a_:~%%i!
   if defined str (
     echo !str!|findstr /b /l "%b_%">nul
     if !errorlevel! EQU 0 if !instr! EQU -1 set instr=%%i
     )
  )
  echo The first position of "%b_%" in "%a_%" is %instr%
  endlocal & goto :EOF

To find the last position:
  @echo off & setlocal enableextensions
  set a_=Hello world, Hello.
  set b_=ll
  call :InstrLastFN "%a_%" "%b_%" position_
  echo The last position of "%b_%" in "%a_%" is %position_%
  endlocal & goto :EOF

  :: ============================================================
  :InstrLastFN
  setlocal enableextensions enabledelayedexpansion
  echo %1|findstr %2>nul
  if %errorlevel% EQU 1 (endlocal & set %3=-1& goto :EOF)
  set rest_=%1
  set /a instr_=-1
  :_loop
    set rest_=%rest_:~1%
    echo !rest_!|findstr %2>nul
    if %errorlevel% EQU 1 (endlocal & set %3=%instr_%& goto :EOF)
    set /a instr_ +=1
    goto _loop
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  The last position of "ll" in "Hello world, Hello." is 15

There are other solution options:
  @echo off & setlocal enableextensions enabledelayedexpansion
  set a_=Hello world, Hello.
  set b_=ll
  set instr=-1
  for /l %%i in (0,1,255) do (
   set str=!a_:~%%i!
   if defined str (
     echo !str!|findstr /b /l "%b_%">nul
     if !errorlevel! EQU 0 set instr=%%i
     )
  )
  echo The last position of "%b_%" in "%a_%" is %instr%
  endlocal & goto :EOF

If you can get hold of QBASIC, the first position can also be solved
as follows
  @echo off & setlocal enableextensions
  set a_=Hello world, Hello.
  set b_=ll
  ::
  > tmp$$$.bas echo OPEN "tmp$$$.cmd" FOR OUTPUT AS #1
  >>tmp$$$.bas echo PRINT #1, "@set p_=";LTRIM$(STR$(INSTR("%a_%", "%b_%")))
  >>tmp$$$.bas echo CLOSE #1
  >>tmp$$$.bas echo SYSTEM
  ::
  qbasic /run tmp$$$.bas
  call tmp$$$.cmd
  ::
  echo The position of "%b_%" in "%a_%" is %p_%
  ::
  for %%f in (tmp$$$.bas tmp$$$.cmd) do if exist %%f del %%f
  endlocal & goto :EOF

The output will be (note the different indexing!)
  D:\TEST>cmdfaq
  The position of "ll" in "Hello world, Hello." is 3

Alternatively, a Visual Basic aided command line script solution
could be used:
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  ::
  set a_=Hello world, Hello.
  set b_=ll
  ::
  :: Run the Visual Basic Script
  cscript //nologo tmp$$$.vbs
  ::
  :: Run the auxiliary CMD script
  call tmp$$$.cmd
  ::
  echo The position of "%b_%" in "%a_%" is %p_%
  ::
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  Const ForReading = 1, ForWriting = 2, ForAppending = 8       'VBS
  Dim a, b, p, FSO, fout                                       'VBS
  Set WshShell = WScript.CreateObject("WScript.shell")         'VBS
  a=WshShell.ExpandEnvironmentStrings("%a_%")                  'VBS
  b=WshShell.ExpandEnvironmentStrings("%b_%")                  'VBS
  p = Instr(1, a, b, 1)                                        'VBS
  Set FSO = CreateObject("Scripting.FileSystemObject")         'VBS
  Set fout = FSO.OpenTextFile("tmp$$$.cmd", ForWriting, true)  'VBS
  fout.WriteLine "@set p_=" & p                                'VBS

The output would (again) be
  D:\TEST>cmdfaq
  The position of "ll" in "Hello world, Hello." is 3

References/Comments:
 http://www.google.com/groups?selm=bt7fqj%24475f4%241%40ID-55492.news.uni-berlin.de
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:51 2008
Subject: 51) How can I echo lines in different colors in NT scripts?
Date: Thu,  6 Mar 2008 01:00:51
From: ts@uwasa.fi (Timo Salmi)

There is no easy answer. The COLOR command affects the entire
screen, not just the next output. That's not what we want in this
item. In MS-DOS+Win..95/98/ME one can use ANSI.SYS for the task. In
NT/2000/XP it is possible in principle under COMMAND.COM, but in the
NT-series it is too cumbersome and installing it has too much side
effects to be practical. Therefore a customized solution is needed.
One option is to use "ECHOC.EXE Echo in colors" tool for the task.
It is a Turbo Pascal program included in tscmd.zip. For example one
might have

  @echo off & setlocal enableextensions
  echoc 0 14 On black bright yellow
  echo.
  echoc 1 13 On blue bright magenta
  echo.
  echo back to normal
  endlocal & goto :EOF

Another example to facilitate multiple spaces between words (and
also rainbow lines)

  @echo off
  echoc 0 10 M
  echoc 0 11 y
  echoc 0 0
  echoc 0 0
  echoc 0 12 t
  echoc 0 13 e
  echoc 0 14 s
  echoc 0 15 t
  echo.

If you can get hold of QBASIC, using colors is relatively easy and
much faster. Below is an example
  @echo off & setlocal enableextensions
  for /f "tokens=*" %%f in ("%temp%") do set temp_=%%~sf
  findstr "'%skip%QB" "%~f0" > %temp_%\tmp$$$.bas
  qbasic /run %temp_%\tmp$$$.bas
  for %%f in (%temp_%\tmp$$$.bas) do if exist %%f del %%f
  endlocal & goto :EOF
  ::
  CLS                                              'QB
  COLOR 14,0                                       'QB
  PRINT "A simple ";                               'QB
  COLOR 13,0                                       'QB
  PRINT "color ";                                  'QB
  COLOR 14,0                                       'QB
  PRINT "demonstration"                            'QB
  PRINT "By Prof. Timo Salmi"                      'QB
  PRINT                                            'QB
  FOR j = 0 TO 7                                   'QB
    FOR i = 0 TO 15                                'QB
      COLOR i, j                                   'QB
      PRINT LTRIM$(STR$(i)); " "; LTRIM$(STR$(j)); 'QB
      COLOR 1, 0                                   'QB
      PRINT " ";                                   'QB
    NEXT i                                         'QB
    PRINT                                          'QB
  NEXT j                                           'QB
  SYSTEM                                           'QB

However, there is, after all, a clever trick to get the ANSI.SYS
color codes in XP based on a tip in alt.msdos.batch.nt

  @echo off & setlocal enableextensions
  ::
  :: The file paths
  set ConfigNT=%WinDir%\System32\config.nt
  set ConfigNTbak=%WinDir%\System32\config.nt.bak
  ::
  :: Check that you have a backup of your original CONGIF.NT
  if not exist "%ConfigNTbak%" (
    echo.
    echo Exiting %~f0
    echo "%ConfigNTbak%"
    echo File not found. Needed for restoring config.nt so first run
    echo copy "%ConfigNT%" "%ConfigNTbak%"
    goto :EOF
    )
  ::
  :: Make a copy of the backup as a double safety
  copy "%ConfigNTbak%" "%temp%\CONFIG.NT">nul
  ::
  :: Customize CONFIG.NT to use ANSI.SYS
  > "%ConfigNT%" echo DOSONLY
  >>"%ConfigNT%" echo dos=high, umb
  >>"%ConfigNT%" echo device=%%SystemRoot%%\system32\himem.sys
  >>"%ConfigNT%" echo files=40
  >>"%ConfigNT%" echo DEVICE=%WinDir%\System32\ANSI.SYS /x
  ::
  :: Choose MS-DOS color
  cls
  command /cecho [0;40;36;1mThis should appear in cyan [0;40;31;1mand this in red
  ::
  :: Restore the original CONFIG.NT
  copy "%temp%\CONFIG.NT" "%WinDir%\System32\">nul
  if exist "%temp%\CONFIG.NT" del "%temp%\CONFIG.NT">nul
  ::
  :: Check if loading ANSI was successful
  mem /c | find /i " ansi ">nul
  if %errorlevel% GTR 0 (
    echo.
    echo Warning: ANSI not loaded
    )
  endlocal & goto :EOF

After successfully running the above script in the CMD.EXE ANSI
escape sequences can be used in the other scripts applying the
following format of the echo
  command /cecho TheAnsiSequence + WhateverText

A demonstration with ANSI.SYS generated colors
  @echo off & setlocal enableextensions enabledelayedexpansion
  cls
  set cecho_=command /cecho
  for /l %%i in (0,1,7) do (
    for /l %%j in (2,1,9) do (
      set /a k=%%j-2
      %cecho_% [%%j;%%i1H[4!k!;3%%im[4!k!;3%%i;1m
      )
    )
  %cecho_% [40;30;1mThe end of the demo by Prof. Timo Salmi
  endlocal & goto :EOF

Another, similar demo:
  @echo off & setlocal enableextensions
  set cecho=echo
  mem /c | find /i " ansi ">nul
  if %errorlevel% EQU 0 (
    set cecho=command /cecho
    set fg_red0=[0;31m
    set fg_red=[0;31;1m
    set fg_green0=[0;32m
    set fg_green=[0;32;1m
    set fg_yellow0=[0;33m
    set fg_yellow=[0;33;1m
    set fg_blue0=[0;34m
    set fg_blue=[0;34;1m
    set fg_magenta0=[0;35m
    set fg_magenta=[0;35;1m
    set fg_cyan0=[0;36m
    set fg_cyan=[0;36;1m
    set fg_white0=[0;37m
    set fg_white=[0;37;1m
    )
  %cecho% %fg_red0%fg_red0 %fg_red%fg_red
  %cecho% %fg_green0%fg_green0 %fg_green%fg_green
  %cecho% %fg_yellow0%fg_yellow0 %fg_yellow%fg_yellow
  %cecho% %fg_blue0%fg_blue0 %fg_blue%fg_blue
  %cecho% %fg_magenta0%fg_magenta0 %fg_magenta%fg_magenta
  %cecho% %fg_cyan0%fg_cyan0 %fg_cyan%fg_cyan
  %cecho% %fg_white0%fg_white0 %fg_white%fg_white
  endlocal & goto :EOF

The advantage of the CONFIG.NT method over using an external program
such as my ECHOC.EXE to output in colors is that it is faster. Note
that there are limitations to the screen display modes the method
can handle. The safest and the most obvious is to use to the 80x25
mode.

References/Comments:
 http://www.google.com/groups?selm=bts0me%24e7b%40poiju.uwasa.fi
 http://www.google.com/groups?selm=40F2CE8D.98194BFA%40yahoo.com.au
 http://www.google.com/groups?selm=1178279717.580298.7190%40n76g2000hsh.googlegroups.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:52 2008
Subject: 52) How can I enter a password into a variable without echoing it?
Date: Thu,  6 Mar 2008 01:00:52
From: ts@uwasa.fi (Timo Salmi)

This is a task that is best done with the help of Visual Basic
program which the actual CMD script creates. Note that the resultant
password variable is made available to the CMD script since this is
a CMD, not a VBS FAQ.

  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo tmp$$$.vbs
  :: Call the command line script wchich the script host built
  call tmp$$$.cmd
  :: Clean up
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  :: Demonstrate the result
  echo The entered password was %PassWord%
  endlocal & goto :EOF
  '
  'The Visual Basic Script
  Set WshShell = WScript.CreateObject("WScript.shell")                 'VBS
  Set WshPass  = WScript.CreateObject("ScriptPW.Password")             'VBS
  WScript.StdOut.Write "Password: "                                    'VBS
  Password=WshPass.GetPassWord()                                       'VBS
  WScript.Echo                                                         'VBS
  WshShell.run "cmd /c echo @set PassWord=" & PassWord & ">tmp$$$.cmd" 'VBS
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:53 2008
Subject: 53) How can I quietly test if a disk device is ready or not?
Date: Thu,  6 Mar 2008 01:00:53
From: ts@uwasa.fi (Timo Salmi)

You might first wish to revisit item #9 about suppressing error
messages.
  @echo off & setlocal enableextensions
  ::
  :: Check the usage
  if "%1"=="" (
    echo Usage: %~f0 [DiskDevice:]
    goto :EOF)
  for %%d in (a: b: c: d: e: f: g: h: i: j: k: l: m: n:
              o: p: q: r: s: t: u: v: w: x: y: z:) do (
              if /i "%%d"=="%1" goto _set)
  echo Usage: %~f0 [DiskDevice:]
  echo The DiskDevice must be A: - Z:
  goto :EOF
  ::
  :: Do the testing and set a relevant result environment variable
  :_set
  set ready=true
  dir %1 > "%temp%\tmp$$$.dir" 2>&1
  find "The device is not ready" "%temp%\tmp$$$.dir" > nul
  if %errorlevel% EQU 0 set ready=false
  find "The system cannot find the path specified" "%temp%\tmp$$$.dir" > nul
  if %errorlevel% EQU 0 set ready=false
  ::
  :: Show the result
  if "%ready%"=="true"  echo The device %1 is ready
  if "%ready%"=="false" echo The device %1 is not ready
  ::
  :: Clean up
  if exist "%temp%\tmp$$$.dir" del "%temp%\tmp$$$.dir"
  endlocal & goto :EOF

The output might be e.g.
  D:\TEST>cmdfaq a:
  The device a: is not ready

References/Comments:
 http://www.google.com/groups?selm=1p5ama23spm2o%24.p75bwbfnbwep%24.dlg%4040tude.net
 http://www.google.com/groups?selm=1194012165.466550.283660%40y42g2000hsy.googlegroups.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:54 2008
Subject: 54) How can I get the type of a disk device?
Date: Thu,  6 Mar 2008 01:00:54
From: ts@uwasa.fi (Timo Salmi)

Utilizing Visual Basic in the CMD script we get:
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  ::
  :: Check the usage
  if "%1"=="" (
    echo Usage: %~f0 [DiskDevice:]
    goto :EOF)
  for %%d in (a: b: c: d: e: f: g: h: i: j: k: l: m: n:
              o: p: q: r: s: t: u: v: w: x: y: z:) do (
              if /i "%%d"=="%1" goto _set)
  echo Usage: %~f0 [DiskDevice:]
  echo The DiskDevice must be A: - Z:
  goto :EOF
  ::
  :_set
  set drive_=%1
  ::
  :: Run the Visual Basic Script
  cscript //nologo tmp$$$.vbs
  ::
  :: Run the auxiliary CMD script
  call tmp$$$.cmd
  ::
  :: Show the results
  echo Drive %drive_% is of type %drivetype_%
  ::
  :: Clean up
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  Const ForReading = 1, ForWriting = 2, ForAppending = 8       'VBS
  Dim FSO, fout, drive, d, dtype                               'VBS
  Set WshShell = WScript.CreateObject("WScript.shell")         'VBS
  drive=WshShell.ExpandEnvironmentStrings("%drive_%")          'VBS
  Set FSO = CreateObject("Scripting.FileSystemObject")         'VBS
  If Not FSO.DriveExists(drive) Then                           'VBS
    dtype = "Not found"                                        'VBS
  Else                                                         'VBS
    Set d = fso.GetDrive(drive)                                'VBS
    Select Case d.DriveType                                    'VBS
       Case 0: dtype = "Unknown"                               'VBS
       Case 1: dtype = "Removable"                             'VBS
       Case 2: dtype = "Fixed"                                 'VBS
       Case 3: dtype = "Network"                               'VBS
       Case 4: dtype = "CD-ROM"                                'VBS
       Case 5: dtype = "RAM Disk"                              'VBS
       Case Else dtype = "Not recognized"                      'VBS
    End Select                                                 'VBS
    If d.IsReady Then                                          'VBS
      dtype = dtype & "; Ready"                                'VBS
    Else                                                       'VBS
      dtype = dtype & "; Not ready"                            'VBS
    End if                                                     'VBS
  End If                                                       'VBS
  Set fout = FSO.OpenTextFile("tmp$$$.cmd", ForWriting, true)  'VBS
  fout.WriteLine "@set drivetype_=" & dtype                    'VBS

The output could be e.g.
  D:\TEST>cmdfaq P:
  Drive P: is of type Network; Not ready

A batch only method, but requiring administrator privileges, to test
e.g. for a CD-ROM dirve is
  @echo off & setlocal enableextensions
  (fsutil fsinfo drivetype Z:|find "CD-ROM Drive">nul)^
    && echo Z: is a CD-ROM Drive || echo Z: is not a CD-ROM Drive
  endlocal & goto :EOF

The output could be e.g.
  D:\TEST>cmdfaq
  Z: is a CD-ROM Drive

A related question. How does one detect the drive letter of the
CD-ROM drive on a PC? This method works only if you are logged on as
"an administrator or a member of the Administrators group".
  @echo off & setlocal enableextensions enabledelayedexpansion
  for %%d in (C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
    %comspec% /c if exist %%d:\ (
      fsutil fsinfo drivetype %%d:|find "CD-ROM Drive">nul
      if !errorlevel! EQU 0 set cdletter=%%d
    )
  )
  echo CD-ROM found on drive %cdletter%:
  endlocal & goto :EOF

An example of the output:
  C:\_D\TEST>cmdfaq
  CD-ROM found on drive Z:

Revisit item #53 for testing whether the drive is ready or not.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:55 2008
Subject: 55) How to get the creation, last modified and last access of a file?
Date: Thu,  6 Mar 2008 01:00:55
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  :: Get the file name
  if [%1]==[] (echo Usage: %~f0 FileName & goto :EOF)
  if not exist "%~f1" (echo File %~f1 not found & goto :EOF)
  set fname_=%~f1
  ::
  :: Display the information
  for /f %%f in ('dir "%fname_%" /s /b /-c /a:-d-s-h') do echo %%~ff
  echo Created:
  for /f "skip=5 tokens=*" %%f in (
    'dir "%fname_%" /tc /-c /a:-d-s-h^|find /v "(s)"') do echo %%f
  echo Last written:
  for /f "skip=5 tokens=*" %%f in (
    'dir "%fname_%" /tw /-c /a:-d-s-h^|find /v "(s)"') do echo %%f
  echo Last accessed:
  for /f "skip=5 tokens=*" %%f in (
    'dir "%fname_%" /ta /-c /a:-d-s-h^|find /v "(s)"') do echo %%f
  endlocal & goto :EOF

Note that depending on the date/time format specified in your
computer's regional settings the output may vary. The output might
be something like
  D:\TEST>cmdfaq batfaq.bat
  D:\TEST\BATFAQ.BAT
  Created:
  14.11.2003  04:06               118 BATFAQ.BAT
  Last written:
  19.02.2004  13:11               118 BATFAQ.BAT
  Last accessed:
  21.02.2004  16:52               118 BATFAQ.BAT

Depending on what exactly we want, the above solution is not
necessarily satisfactory. The VBS assisted solution below put the
information first into accessible environment variables.
Furthermore, it includes the seconds in the file time stamp.

  @echo off & setlocal enableextensions
  ::
  :: Get the file name
  if [%1]==[] (echo Usage: %~f0 FileName & goto :EOF)
  if not exist "%~f1" (echo File %~f1 not found & goto :EOF)
  set fname_=%~f1
  ::
  :: Build a Visual Basic Script
  findstr "'VBS" "%~f0"|findstr /v "findstr" > tmp$$$.vbs
  ::
  :: Run the Visual Basic Script
  cscript //nologo tmp$$$.vbs
  ::
  :: Call the command line script wchich the script host built
  call tmp$$$.cmd
  ::
  :: Clean up
  for %%f in (tmp$$$.vbs tmp$$$.cmd) do if exist %%f del %%f
  ::
  :: Demonstrate the result
  echo %fname_%
  echo Size:          %~z1 bytes
  echo Created:       %fdc%
  echo Last modified: %flm%
  echo Last accessed: %fla%
  ::
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  Const ForReading = 1, ForWriting = 2, ForAppending = 8       'VBS
  Dim FileName, FSO, fin, fout                                 'VBS
  Set WshShell = WScript.CreateObject("WScript.shell")         'VBS
  Set FSO = CreateObject("Scripting.FileSystemObject")         'VBS
  '
  FileName=WshShell.ExpandEnvironmentStrings("%fname_%")       'VBS
  Set fin = FSO.GetFile(FileName)                              'VBS
  '
  Set fout = FSO.OpenTextFile("tmp$$$.cmd", ForWriting, true)  'VBS
  fout.WriteLine "@set fdc=" & fin.DateCreated                 'VBS
  fout.WriteLine "@set flm=" & fin.DateLastModified            'VBS
  fout.WriteLine "@set fla=" & fin.DateLastAccessed            'VBS
  fout.Close                                                   'VBS

The output might be something like
  D:\TEST>cmdfaq batfaq.bat
  D:\TEST\BATFAQ.BAT
  Size:          118 bytes
  Created:       14.11.2003 04:06:54
  Last modified: 19.02.2004 13:11:32
  Last accessed: 21.02.2004 16:52:49

Incidentally, would you have wanted the file size via the VBS
script then e.g.
  fout.WriteLine "@set fsz=" & fin.size                        'VBS

Also see
 FILEINFO.CMD "CMD shell for FILEINFO.VBS"
 FILEINFO.VBS "FileInfo Visual Basic Script"

References/Comments:
 http://www.google.com/groups?selm=OvgPX+CSR2OAFwIi%40merlyn.demon.co.uk
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:56 2008
Subject: 56) How to find and move more recent files from one folder to another?
Date: Thu,  6 Mar 2008 01:00:56
From: ts@uwasa.fi (Timo Salmi)

Actually, this task is very near what XCOPY /D /V /F /W
C:\SOURCE\*.* C:\TARGET does. With one important difference. XCOPY
does not move files. Even if this task could be attempted with the
CMD.EXE tools presented thorughtout this FAQ, the more complicated
and specific a task gets, the batter to resort to use a programming
language. A Visual Basic Script XPMOVE.VBS is included for the task.
Moving files aways involves some danger. Use the material carefully,
and as always, at your own risk.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:57 2008
Subject: 57) How do I get a list of all my empty folders on c:\ ?
Date: Thu,  6 Mar 2008 01:00:57
From: ts@uwasa.fi (Timo Salmi)

Empty folders, i.e. no files or subfolders. (But first an important
WARNING! Do not go and indiscriminately delete empty folders, since
the system or the programs on your computer may need them.) Here is
one solution option. I earlier attempted this with a "pure" CMD
script, but because of the possibility of hidden files and hidden
subfolders the results were too unstable.

Note that on a shared or system-managed computer you might get
access denied errors. If so, do not start high up the root of C:\

  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  :: Start from Folder (Customize, if need be)
  set StartFold_=C:\_D
  :: Run the VBS script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%temp%\tmp$$$.vbs"
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs") do if exist %%f del %%f
  endlocal & goto :EOF

  Function NumberOfFilesInFolder(FolderName) 'VBS
    Dim fso, f, f1, fc, CountFiles 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(FolderName) 'VBS
    Set fc = f.Files 'VBS
    CountFiles = 0 'VBS
    For Each f1 in fc 'VBS
      CountFiles = CountFiles + 1 'VBS
    Next 'VBS
    NumberOfFilesInFolder = CountFiles 'VBS
  End Function 'VBS

  Function NumberOfFoldersInFolder(FolderName) 'VBS
    Dim fso, f, f1, fc, CountFolders 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(FolderName) 'VBS
    Set fc = f.SubFolders 'VBS
    CountFolders = 0 'VBS
    For Each f1 in fc 'VBS
      CountFolders = CountFolders + 1 'VBS
    Next 'VBS
    NumberOfFoldersInFolder = CountFolders 'VBS
  End Function 'VBS

  Function TraverseSubFolders(StartFolderName) 'VBS
    Dim fso, f, f1, sf, nFil, nFol 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    Set f = fso.GetFolder(StartFolderName) 'VBS
    Set sf = f.SubFolders 'VBS
    For Each f1 in sf 'VBS
      nFil = NumberOfFilesInFolder(f1) 'VBS
      nFol = NumberOfFoldersInFolder(f1) 'VBS
      if (CLng(nFil) = 0) And (CLng(nFol) = 0) Then 'VBS
        Wscript.Echo f1 'VBS
      End If 'VBS
      TraverseSubFolders(f1) 'VBS
    Next 'VBS
  End Function 'VBS

  Function TraverseFolders(StartFolderName) 'VBS
    Dim fso, f, f1, sf, nFil, nFol 'VBS
    Set fso = CreateObject("Scripting.FileSystemObject") 'VBS
    If (fso.FolderExists(StartFolderName)) Then 'VBS
      Set f = fso.GetFolder(StartFolderName) 'VBS
      nFil = NumberOfFilesInFolder(f) 'VBS
      nFol = NumberOfFoldersInFolder(f) 'VBS
      if (CLng(nFil) = 0) And (CLng(nFol) = 0) Then 'VBS
        Wscript.Echo f 'VBS
      End If 'VBS
      TraverseSubFolders(f) 'VBS
    Else 'VBS
      Wscript.Echo "Folder " & StartFolderName & " not found" 'VBS
      Wscript.Quit 'VBS
    End If 'VBS
  End Function 'VBS

  Dim WshShell, StartAtFolder 'VBS
  Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
  StartAtFolder = WshShell.ExpandEnvironmentStrings("%StartFold_%") 'VBS
  TraverseFolders StartAtFolder 'VBS

In pure CMD script one could try
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f "tokens=1 delims=" %%d in ('dir /s /b /a:d c:\_m') do (
    call :DirEmpty "%%d"
    if "!empty_!"=="true" echo %%d)
  endlocal & goto :EOF
  ::
  :: ======================================================
  :DirEmpty
  set empty_=true
  dir %1 /a 2>&1 | find "File(s)" | find /v " 0 File(s)" > nul
  if !errorlevel! EQU 0 set empty_=false
  dir %1 /a 2>&1 | find "Dir(s)" | find /v " 2 Dir(s)" > nul
  if !errorlevel! EQU 0 set empty_=false
  goto :EOF

References/Comments:
 http://www.google.com/groups?selm=1j32amiapq3hr%24.g7jzi5lnl8wk%24.dlg%4040tude.net

http://www.google.com/groups?selm=v6em6ps8xyh4.mms%40MRC.MIR.SID.75
  @echo off
  for /r \ /d %%a in (*) do (
  dir /b /s /a "%%a"|findstr .>nul
  if errorlevel 1 echo %%a)

With slight adjustments to the inventive original formulation by
Dean Wells in news: microsoft.public.win2000.cmdprompt.admin we can
use
  @echo off & setlocal enableextensions
  dir C:\MyFolder\*.* /a /b^
   | find /v "SomeUnlikelyString">nul && echo NOT empty || echo Empty
  endlocal & goto :EOF
As a sideline, note the usage of the caret ^ for dividing a command
structure over several lines to avoid wrapping problems in
presenting a solution.

Another sideline, about || && and redirection:
  foxidrive wrote:
  > On Mon, 20 Nov 2006 19:14:42 +0200, Timo Salmi <ts@uwasa.fi> of a question made to him:
  >>> setlocal enableextensions
  >>> vol K: |find "48C4-AE69" && echo Backup Samsung || echo Backup Western Digital >>%path_to_start%backup.log
  >>> endlocal
  (Fails. Why?)
  --- end of the forwarded quote ---

  > I can confirm that adding redirection to such a line changes the
  > behavior, and that enclosing the command in ( ) restores it.
  > You can test it with these two lines.
  >
  > (echo b|find "a">nul && echo 0 ||echo 1) >a.txt
  > (echo a|find "a">nul && echo 0 ||echo 1) >a.txt

  Good catch. Some further trials show that same effect can be
  achieved by redirecting the output of the script outside it rather
  than within it. Thus the following also works

    @echo off & setlocal enableextensions
    rem C:\_D\TEST\CMDFAQ.CMD
    echo b|find "a">nul && echo yes|| echo no
    echo a|find "a">nul && echo yes|| echo no
    endlocal & goto :EOF

    C:\_D\TEST>CMDFAQ.CMD > a.txt
  The contents of a.txt will be
    no
    yes
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:58 2008
Subject: 58) How do I best combine two quoted arguments into one quoted string?
Date: Thu,  6 Mar 2008 01:00:58
From: ts@uwasa.fi (Timo Salmi)

Consider two cases. First, the arguments are in environment
variables:
  @echo off & setlocal enableextensions
  set x_="C:\Program Files\Schedule\"
  set y_="My log.txt"
  set z1_="%x_:"=%%y_:"=%"
  echo.%z1_%
  goto :EOF
The output will be
  D:\TEST>cmdfaq
  "C:\Program Files\Schedule\My log.txt"

Second, the argument are given as replaceable parameters to the
script:
  @echo off & setlocal enableextensions
  set z2_="%~1%~2"
  echo.%z2_%
  goto :EOF
The output will be
  D:\TEST>cmdfaq "C:\Program Files\Schedule\" "My log.txt"
  "C:\Program Files\Schedule\My log.txt"

The tilde ~ is essential in the second version. As the documentation
about "Using batch parameters" in "Command-line reference" says:
%~1 Expands %1 and removes any surrounding quotation marks ("").

Alternatively, (since e.g. NT4 does not recognize the ~trick) one
could use
  @echo off & setlocal enableextensions
  set x_=%1
  set y_=%2
  set z1_="%x_:"=%%y_:"=%"
  echo.%z1_%
  goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:00:59 2008
Subject: 59) How do I find if a folder exists? How about visible files in it?
Date: Thu,  6 Mar 2008 01:00:59
From: ts@uwasa.fi (Timo Salmi)

The trick advocated in the Microsoft Command-line reference is
  "if exist c:mydir\nul goto process"
However, the advocated method crumbles with the LFN possibility of
spaces in the folder names. Hence
  if not exist "c:my dir\nul" echo Folder not found
will always be true whether the folder exists or not.

One solution to the problem would appear to be:
  @echo off & setlocal enableextensions
  rem echo on   %This is for debugging purposes%
  ::
  :: Which folder to examine (customize the path!)
  set dr_=c:\my dir
  ::
  if not exist "%dr_%\*.*" (
    echo Folder "%dr_%" not found)
  ::
  if exist "%dr_%\*.*" (
    echo Folder "%dr_%" exists)
  ::
  dir "%dr_%" 2>&1 | find "File(s)" | find /v " 0 File(s)" > nul
  if %errorlevel% NEQ 0 (
    echo No visible files in folder "%dr_%")
  ::
  dir "%dr_%" 2>&1 | find "File(s)" | find /v " 0 File(s)" > nul
  if %errorlevel% EQU 0 (
    echo Visible files in found in folder "%dr_%")
  ::
  endlocal & goto :EOF

Phil Robyn pointed out in email that leaving out the \nul the
following kind of a formulation works.
  if not exist "%dr_%" (
    echo Folder "%dr_%" not found
    goto :EOF)

Yet another option is to utilize the fact that short file names do
not have a problem with \nul
  @echo off & setlocal enableextensions
  :: Which folder to examine (customize the path!)
  set dr_=m:\my dir
  :: Test it
  for /f "tokens=1 delims=" %%d in ("%dr_%") do (
    if exist %%~sd\nul (
     echo Found %%d
      ) else (
     echo Did not find %%d))
  endlocal & goto :EOF

Also see the item "75) How do I detect if an object is a file or a
folder?"

References/Comments:
 http://www.google.com/groups?selm=c2uroi%24pvs%2406%241%40news.t-online.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:00 2008
Subject: 60) How do I delete all but most recent 20 files in a folder?
Date: Thu,  6 Mar 2008 01:01:00
From: ts@uwasa.fi (Timo Salmi)

The example below comes with multiple safeguards. It prepares a new
script, which you then can run. The resulting script comes with
rem:s and the deletion with the /p (prompt for confirmation) switch.
The possibility of file/folder names with spaces has been taken into
account.
  @echo off & setlocal enableextensions
  ::
  :: Which folder to examine (customize the path!)
  set targetdir_=c:\_m\test 2
  if not exist "%targetdir_%\*.*" (
    echo Folder "%targetdir_%" not found
    goto :EOF)
  ::
  :: Let the script prepare a new one (customize the path!)
  set script_="c:\_m\doit.cmd"
  if exist %script_% del %script_%
  ::
  :: Identify the files to be deleted
  for /f "skip=20 delims=" %%f in ('dir /a:-d /b /o:-d "%targetdir_%\*.*"') do (
    echo rem del /p "%targetdir_%\%%~nf%%~xf">>%script_%)
  ::
  :: Tell me about it
  for /f "delims=" %%s in (%script_%) do if exist %%~fs (
   echo The script "%%~fs" is ready
   echo %%~ts %%~as %%~zs)
  goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:01 2008
Subject: 61) How can one devise a command line calculator?
Date: Thu,  6 Mar 2008 01:01:01
From: ts@uwasa.fi (Timo Salmi)

There are several options. A fairly trivial, but severely limited
option is using the SET /A command. For example
  @echo off & setlocal enableextensions
  set /a x=4+7
  echo %x%
  endlocal & goto :EOF
The output would be
  D:\TEST>cmdfaq
  11

A second option is using G(nu)AWK. For example
  @echo off & setlocal enableextensions
  gawk 'BEGIN{printf"%%s\n",4/7}'
  endlocal & goto :EOF
The output would be
  D:\TEST>cmdfaq
  0.571429
This option could be used to perform quite complicated calculations.

A third option is using a third-party program such as FN.EXE from
ftp://garbo.uwasa.fi/pc/ts/tsfunc17.zip (or whatever is the current
version number). An example
  D:\TEST>fn sin(45*3.1415926536/180) /b
  0.7071067812

A fourth option is using QBASIC or GWBASIC, if available. For more
see
 FU.BAT Poor man's function evaluator
and the MS-DOS+Win../95/98/ME FAQ ftp://garbo.uwasa.fi/pc/link/tsbat.zip
item "141. Can I calculate factorials in a batch? Do I need
recursion?" which is sufficiently compatible with NT/2000/XP.

A fifth option is letting the CMD.EXE script build a Visual Basic
Script (VBScript)
  @echo off & setlocal enableextensions
  ::
  :: Usage
  if [%1]==[] (
    echo.+----------------------------------------------------+
    echo ^| CCALC.CMD to perform Visual Basic calculations     ^|
    echo ^| By Prof. Timo Salmi, Last modified Wed 24-Mar-2004 ^|
    echo +----------------------------------------------------+
    echo.
    echo Usage: %~f0 Expression
    echo.                                      Result
    echo Examples: CCALC 4 / 7 * 2.5           1.42857142857143
    echo           CCALC Round^(Sqr^(2^),3^)       1.414
    echo           CCALC 2^^^^4                  16 [Note the need of double carets ^^]
    echo           CCALC 103 Mod 10            3
    echo           CCALC 103 \ 10              10
    echo           CCALC Exp^(1^)                2.71828182845905
    echo           CCALC Log^(10^)               2.30258509299405
    echo           CCALC Sin^(45*Pi/180^)        0.707106781186547
    echo           CCALC CDbl^(Rnd^)             0.575344264507294
    echo           CCALC Int^(^(50-10+1^)*Rnd+10^) [A random integer 10...50]
    echo           CCALC Hex^(254^)              FE
    goto :EOF)
  ::
  :: Make a temporary folder
  if not exist c:\mytemp mkdir c:\mytemp
  ::
  :: Build a Visual Basic Script
  echo Randomize>c:\mytemp\vbscalc.vbs
  echo Const pi=3.14159265358979>>c:\mytemp\vbscalc.vbs
  echo WScript.Echo Eval("%*")>>c:\mytemp\vbscalc.vbs
  ::
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\vbscalc.vbs>c:\mytemp\result.txt
  ::
  :: The result from the optional output file
  type c:\mytemp\result.txt
  ::
  :: Clean up (leave c:\mytemp\result.txt if need be)
  for %%f in (c:\mytemp\vbscalc.vbs c:\mytemp\result.txt) do (
    if exist %%f del %%f)
  rmdir c:\mytemp
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=IAG%2B8LBTqJYAFwrp%40merlyn.demon.co.uk
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:02 2008
Subject: 62) How can I compare within a script if two files are identical?
Date: Thu,  6 Mar 2008 01:01:02
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  set file1_=d:\test\koe.cmd
  set file2_=d:\test\koe 2.cmd
  set file2_=m:\koe.cmd
  if not exist "%file1_%" (
    echo File %file1_% not found
    goto :EOF)
  if not exist "%file2_%" (
    echo File %file2_% not found
    goto :EOF)
  ::
  fc /b "%file1_%" "%file2_%">nul
  echo %file1_%
  echo %file2_%
  if %errorlevel% EQU 0 (
    echo The files agree
    ) else (
    echo The files differ)
  endlocal & goto :EOF

However, if you have an OS version where FC does not return an
errorlevel then you have to utilize FIND (or FINDSTR) in conjunction
with FC to get the errorlevel.

  @echo off & setlocal enableextensions
  :
  fc /b "%file1_%" "%file2_%"|find "FC: no differences encountered">nul
  :
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=1d6w0ecevgfj7%24.1pxxinkrblmxz.dlg%4040tude.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:03 2008
Subject: 63) How to perform a command on each a line of file as an argument?
Date: Thu,  6 Mar 2008 01:01:03
From: ts@uwasa.fi (Timo Salmi)

Q: I have an argument file with many lines. I want to perform the
same command with the contents of each line in turn as an argument.
How do I do that.

A: Say that you have the following argument file myargs.txt
  row1
  row2
  row3
  row4
And that you wish to echo (or whatever else) for the argument on
each line in turn.
  @echo off & setlocal enableextensions
  :: The argument file
  set file_=myargs.txt
  if not exist "%file_%" (
    echo File %file_% not found
    goto :EOF)
  ::
  :: Make a temporary folder
  if not exist c:\mytemp mkdir c:\mytemp
  if exist c:\mytemp\doit.cmd del c:\mytemp\doit.cmd
  ::
  :: Whatever command you wish to perform
  :: The example echoes, that is the second ECHO.
  :: That ECHO command is what you would change to whatever
  for /f "delims=" %%r in ('type %file_%') do (
    echo ECHO.%%r>>c:\mytemp\doit.cmd)
  ::
  :: Perform
  call c:\mytemp\doit.cmd
  ::
  :: Clean up
  if exist c:\mytemp\doit.cmd del c:\mytemp\doit.cmd
  rmdir c:\mytemp
  ::
  endlocal & goto :EOF
The contents of doit.cmd will be
  ECHO.row1
  ECHO.row2
  ECHO.row3
  ECHO.row4

With SED the solution to make c:\mytemp\doit.cmd would simply be
  @echo off
  sed -e "s/^/ECHO.&/" myargs.txt>c:\mytemp\doit.cmd

A similar question from alt.msdos.batch.nt
Let's say I have a simple text file that is e.g. 8 lines long, and
each line contains exactly one number. (Each number can be 1 or 2
digits long.) For example:
  2
  5
  12
  1
  15
  6
  7
  2
How do I script my program to take the 8 numbers in the text file,
then output them to a file that contains exactly one line? Also, I
need each number to be semicolon delimited so that the output looks
like this: 2;5;12;1;15;6;7;2

This is the solution:
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f %%a in ('type MyFile.txt') do set s_=!s_!%%a;
  set s_=%s_:~0,-1%
  echo %s_%
  endlocal & goto :EOF
The output will be exactly as asked for.

Actually
  for /f %%a in ('type MyFile.txt') do set s_=!s_!%%a;
can be replaced by
  for /f %%a in (MyFile.txt) do set s_=!s_!%%a;
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:04 2008
Subject: 64) How to count the number of lines in a file, empty lines inclusive?
Date: Thu,  6 Mar 2008 01:01:04
From: ts@uwasa.fi (Timo Salmi)

The dilemma here is that "for /f "delims=" %%r in ('type file')"
will skip empty lines, so one has to ensure there are none. The
trick is to utilize findstr.
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (sixth seventh eight) do (
    echo This is the %%f line>>myfile.txt)
  ::
  :: The counting
  if not exist c:\mytemp mkdir c:\mytemp
  findstr /n "\<*" myfile.txt > c:\mytemp\myfile.tmp
  set lineCount=0
  for /f "delims=" %%r in ('type c:\mytemp\myfile.tmp') do (
    set /a lineCount+=1)
  echo The number of lines is %lineCount%
  ::
  :: Clean up
  for %%f in (myfile.txt c:\mytemp\myfile.tmp) do if exist %%f del %%f
  if exist c:\mytemp rmdir c:\mytemp
  endlocal & goto :EOF
The output will be
  The number of lines is 8

Phil Robyn points out that this "for /f" line version would be
simpler and faster:
  for /f %%a in ('find /v /c "" ^< myfile.txt') do set lineCount=%%a

Other options:
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (sixth seventh eight) do (
    echo This is the %%f line>>myfile.txt)
  echo.>>myfile.txt
  echo.>>myfile.txt
  ::
  :: Count the lines
  for /f %%n in ('find /c /v "" ^< myfile.txt') do set lineCount1=%%n
  echo There are %lineCount1% lines in myfile.txt
  ::
  for /f "delims=:" %%a in ('findstr /n "^.*$" myfile.txt') do (
    set lineCount2=%%a)
  echo There are %lineCount2% lines in myfile.txt
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  There are 9 lines in myfile.txt
  There are 10 lines in myfile.txt
The first method may produce a faulty results.

With G(nu)AWK the solution is
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (sixth seventh eight) do (
    echo This is the %%f line>>myfile.txt)
  ::
  :: The counting
  if not exist c:\mytemp mkdir c:\mytemp
  gawk '{printf "@set lineCount=%%s\n",NR}' myfile.txt>c:\mytemp\tmp.cmd
  call c:\mytemp\tmp.cmd
  ::
  echo The number of lines is %lineCount%
  ::
  :: Clean up
  for %%f in (myfile.txt c:\mytemp\tmp.cmd) do if exist %%f del %%f
  if exist c:\mytemp rmdir c:\mytemp
  endlocal & goto :EOF
The output will (still) be
  The number of lines is 8

Alternatively, a Visual Basic aided command line script solution can
be used
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  for %%i in (1 2 3 4 5 6) do echo This is line %%i>>myfile.txt
  echo.>>myfile.txt
  for %%i in (8 9 10 11 12) do echo This is line %%i>>myfile.txt
  ::
  :: Build a Visual Basic Script
  if not exist c:\mytemp mkdir c:\mytemp
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  ::
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs < myfile.txt > c:\mytemp\tmp$$$.cmd
  ::
  ::
  :: Call the command line script the script host built
  call c:\mytemp\tmp$$$.cmd
  ::
  :: Show the result
  echo The number of lines in myfile.txt is %lines%
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs
              c:\mytemp\tmp$$$.cmd
              myfile.txt) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  i = 0 'VBS
  Do While Not WScript.StdIn.AtEndOfStream 'VBS
    i = i + 1 'VBS
    str = WScript.StdIn.ReadLine 'VBS
  Loop 'VBS
  WScript.StdOut.WriteLine "@set lines=" & i 'VBS
The output will be
  D:\TEST>cmdfaq
  The number of lines in myfile.txt is 12

References/Comments:
 http://www.google.com/groups?selm=1rzseucveq575%24.53nvvmu63px4.dlg%4040tude.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:05 2008
Subject: 65) How do I add text in front and after each line in a text file?
Date: Thu,  6 Mar 2008 01:01:05
From: ts@uwasa.fi (Timo Salmi)

With G(nu)AWK
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4) do (
    echo Line %%f>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (6 7 8 9) do (
    echo Line %%f>>myfile.txt)
  ::
  :: Do it
  <myfile.txt gawk '{printf "Add in front%%sadd after\n",$0}'
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF

With SED
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4) do (
    echo Line %%f>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (6 7 8 9) do (
    echo Line %%f>>myfile.txt)
  ::
  :: Do it
  sed -e "s/.*/Add in front&add after/" myfile.txt
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF

With pure script, but skipping the empty lines!
  @echo off & setlocal enableextensions
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (1 2 3 4) do (
    echo Line %%f>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (6 7 8 9) do (
    echo Line %%f>>myfile.txt)
  ::
  :: Do it
  ::
  :: Clean up
  for %%f in (myfile.txt) do if exist %%f del %%f
  endlocal & goto :EOF

Note how this at the same time answers the question how to remove
empty lines from a text file. One just would apply
  for /f "delims=" %%r in ('type myfile.txt') do (
    echo %%r)
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:06 2008
Subject: 66) How can I delete all the hidden Thumbs.db files from my system?
Date: Thu,  6 Mar 2008 01:01:06
From: ts@uwasa.fi (Timo Salmi)

If you use the "View" | "Thumbnails" option in your Files and
Folders windows, the hidden Thumbs.db system file in each such
folder gradually builds up (if you have not chosen "Do not cache
thumbnails" in Folder Options). To delete them you can use e.g.
following script. It has the option of bypassing the personal
photoalbums folders (mine are at C:\_H\PHOTO and its subfolders.)

  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  echo +-------------------------------------------------------+
  echo ^| THUMBS.CMD Clear the hidden Thumbs.db thumbnail files ^|
  echo ^| By Prof. Timo Salmi, Last modified Fri 18-Jun-2004    ^|
  echo +-------------------------------------------------------+
  ::
  :: Help wanted?
  if /i [%1]==[?] goto _usage
  if /i [%1]==[/?] goto _usage
  ::
  :: Include also the photo folders into the traversing
  if /i [%1]==[all] goto _all
  ::
  :: Ask in general
  set ask_=
  set /p ask_="Traverse some of the hidden Thumbs.db files [y/N]?"
  if /i not "%ask_%"=="y" (endlocal & goto :EOF)
  ::
  :: Delete one by one
  for /f "tokens=* delims=" %%f in (
    'dir /a:h /s /b c:\Thumbs.db^|find /i /v "_h\photo\"') do (
    call :DeleteOneThumb "%%f")
  endlocal & goto :EOF
  ::
  :_all
  :: Ask in general
  set ask_=
  set /p ask_="Traverse ALL hidden Thumbs.db files [y/N]?"
  if /i not "%ask_%"=="y" (endlocal & goto :EOF)
  ::
  :: Delete one by one
  for /f "tokens=* delims=" %%f in (
    'dir /a:h /s /b c:\Thumbs.db') do (
    call :DeleteOneThumb "%%f")
  endlocal & goto :EOF
  ::
  :_usage
  echo.
  echo Usage: THUMBS [all]
  echo        all = traverse also the c:\_h\photo folders
  endlocal & goto :EOF
  ::
  :: =============================================
  :DeleteOneThumb
  dir /a:h %* 2>&1 | find "1 File(s)" > nul
  if %errorlevel% EQU 0 (
    echo.
    for /f "tokens=* delims=" %%f in (%*) do (
      set fsize_=%%~zf
      set fdate_=%%~tf
      set fattr_=%%~af
      )
    echo !fdate_! !fattr_! !fsize_!
    attrib -s -h %* >nul
    del /p %*
    attrib +s +h %* >nul)
  goto :EOF

The essential trick, since the c:\Thumbs.db are hidden/system files
is to detect them. A straight dir will not do that. The /a:h (or
/a:-d or /a) switch is needed. As an aside note how the /A switch
alone can be interpreted as "ALL", undocumented by DIR /?.

The task could be also done with a single command using DEL to
traverse the disk. (See DEL /?). However, I am a bit reticent about
using such potent methods. Furthermore, the selective exclusion of
groups of files is a problem in this option. Likewise giving the
file size, file date and file attribute information prior asking for
deletion.

References/Comments:
 http://www.google.com/groups?selm=cas9g9%24kt0%2403%241%40news.t-online.com
 http://www.google.com/groups?selm=c2def5%24q1o%40poiju.uwasa.fi
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:07 2008
Subject: 67) Is it possible to send a script variable value to the clipboard?
Date: Thu,  6 Mar 2008 01:01:07
From: ts@uwasa.fi (Timo Salmi)

Obviously yes. The following snippet is from the inventive Visual
Basic Script using Internet Explorer that was posted by Marco Maier
Said, Message-ID: <nkya6kho625d$.mms@MRC.MIR.SID.75>

  @echo off
  echo Set oIE =_ >tmp$$$.vbs
  echo WScript.Createobject("InternetExplorer.Application")>>tmp$$$.vbs
  echo oIE.Navigate "about:blank">>tmp$$$.vbs
  echo oIE.Document.parentWindow.clipboardData.getData _>>tmp$$$.vbs
  echo "text",WScript.Arguments(0)>>tmp$$$.vbs
  echo oIE.Quit>>tmp$$$.vbs
  cscript //nologo tmp$$$.vbs "%~1"
  del tmp$$$.vbs

If that won't work get CLIP.EXE from the Windows98 Resource Kit at
ftp://ftp.microsoft.com/Services/TechNet/samples/PS/Win98/Reskit/FILE
or copy a more recent version from Windows Server 2003's
C:\%windir%\system32 folder.

-From: Marco Maier
-Date: Wed Jun 16 20:48:47 EET 2004
-Timo Salmi wrote in message <news:caoqgk$dbl@poiju.uwasa.fi> :

 > My question about reversing. How does one get data from the
 > clipboard to a script environment variable?

 Here is what you asked:

 @echo off
 >_.vbs echo Wscript.StdOut.Write clp
 >>_.vbs echo function clp
 >>_.vbs echo with createobject("internetexplorer.application")
 >>_.vbs echo .navigate "about:blank" : clp = _
 >>_.vbs echo .document.parentwindow.clipboardData.getData ("text")
 >>_.vbs echo .quit : end with : end function
 for /f "tokens=*" %%a in ('cscript /nologo _.vbs') do set clip=%%a
 del _.vbs
- end of the posting -

References/Comments:
 http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/reference/objects/internetexplorer.asp
 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/WinUI/WindowsUserInterface/DataExchange/Clipboard/ClipboardReference/ClipboardFunctions/SetClipboardData.asp
 http://blogs.msdn.com/abhinaba/archive/2006/07/14/665551.aspx
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:08 2008
Subject: 68) How can I test if a program already has been loaded?
Date: Thu,  6 Mar 2008 01:01:08
From: ts@uwasa.fi (Timo Salmi)

In XP one can use Task Manager for the purpose e.g. as follows

  @echo off & setlocal enableextensions
  tasklist|find "Netscp.exe ">nul
  if %errorlevel% EQU 0 (
    echo Netscape has been loaded
  ) ELSE (
    echo Netscape has not been loaded)
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=2u7slvF28684tU1%40uni-berlin.de
References/Comments (for NT/2000):
 http://technet.microsoft.com/en-us/sysinternals/bb896649.aspx

If you are using a script in a command window to call an MS-DOS
program, and you wish to prevent calling that same program
simultaneously from another window/or via shelling (to avoid
datafile or whatever conflicts), you can proceed as shown below. The
script creates a lockfile for the duration of running the script.

  @echo off & setlocal enableextensions
  if exist "%temp%\vpp3d.mrk" (
    echo Exiting: vpp3d already is running
    echo If this is in error delete %temp%\vpp3d.mrk
    goto :EOF)
  echo Mark vpp3d>"%temp%\vpp3d.mrk"
  ::
  :: Call whatever program it happens to be
  C:\_F\VPP\VPP3D.COM
  ::
  del %temp%\vpp3d.mrk
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:09 2008
Subject: 69) How do I get the first, or the last, 400 lines of a file?
Date: Thu,  6 Mar 2008 01:01:09
From: ts@uwasa.fi (Timo Salmi)

A question of "head" and "tail" in Unix terminology. This is a task
that is so much easier to do with SED that only those solutions are
presented. First the "head"

  @echo off
  sed -n 1,400p myfile.txt

Alternatively, and with a test demonstration for the first seven
lines
  @echo off & setlocal enableextensions
  for %%r in (1 2 3 4) do echo line %%r>>myfile.txt
  echo.>>myfile.txt
  for %%r in (6 7 8 9) do echo line %%r>>myfile.txt
  ::
  sed 7q myfile.txt
  ::
  for %%f in (myfile.txt) do del %%f
  endlocal & goto :EOF
The output will be
  line 1
  line 2
  line 3
  line 4

  line 6
  line 7

Getting just the first line
  @echo off & setlocal enableextensions
  for %%r in (1 2 3 4) do echo line %%r>>myfile.txt
  echo.>>myfile.txt
  for %%r in (6 7 8 9) do echo line %%r>>myfile.txt
  ::
  set /p first_=<myfile.txt
  echo %first_%
  ::
  for %%f in (myfile.txt) do del %%f
  endlocal & goto :EOF
The output
  C:\_D\BAS>cmdfaq
  line 1

What about the last lines? That is "tail". From a sed one-liner's
collection by Eric Pement
  sed -e :a -e "$q;N;401,$D;ba" myfile.txt

Furthermore, the are head and tail (and sed and gawk) UNIX ports
e.g. in
 878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip
 UnxUpdates.zip Updates for UnxUtils GNU utilities for native Win32

A Visual Basic Script (VBScript) aided command line script version
of "head"
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  for %%i in (1 2 3 4 5 6) do echo This is line %%i>>MyFile.txt
  echo.>>MyFile.txt
  for %%i in (8 9 10 11 12) do echo This is line %%i>>MyFile.txt
  ::
  :: Build a Visual Basic Script
  set skip=
  set vbs_=%temp%\vhead.vbs
  for /f "tokens=*" %%f in ("%vbs_%") do set vbs_=%%~sf
  findstr "'%skip%VBS" "%~f0" > %vbs_%
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo %vbs_% 5 < MyFile.txt
  ::
  :: Clean up
  for %%f in (%vbs_% MyFile.txt) do del %%f
  endlocal & goto :EOF
  '
  '.......................................................
  'The Visual Basic Script
  '
  StopAfter=WScript.Arguments.Unnamed(0)   'VBS
  i = 0                                    'VBS
  Do While Not WScript.StdIn.AtEndOfStream 'VBS
    str = WScript.StdIn.ReadLine           'VBS
    i = i + 1                              'VBS
    If i <= CInt(StopAfter) Then           'VBS
      WScript.StdOut.WriteLine str         'VBS
    End If                                 'VBS
  Loop                                     'VBS
The output will be
  C:\_D\TEMP>cmdfaq
  This is line 1
  This is line 2
  This is line 3
  This is line 4
  This is line 5

A Visual Basic Script (VBScript) aided command line script version
of "tail"
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  for %%i in (1 2 3 4 5 6) do echo This is line %%i>>MyFile.txt
  echo.>>MyFile.txt
  for %%i in (8 9 10 11 12) do echo This is line %%i>>MyFile.txt
  ::
  :: Build a Visual Basic Script
  set skip=
  set vbs_=%temp%\vtail.vbs
  for /f "tokens=*" %%f in ("%vbs_%") do set vbs_=%%~sf
  findstr "'%skip%VBS" "%~f0" > %vbs_%
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo %vbs_% "MyFile.txt" 3
  ::
  :: Clean up
  for %%f in (%vbs_% MyFile.txt) do del %%f
  endlocal & goto :EOF
  '
  '.......................................................
  'The Visual Basic Script
  '
  ' Define some constants
  Const ForReading = 1, ForWriting = 2, ForAppending = 8       'VBS
  Dim fileName, FSO, f, i, n, nArg, s                          'VBS
  '
  ' Check the right usage
  nArg = WScript.Arguments.Count                               'VBS
  If (nArg = 0) Or (nArg > 2) Then                             'VBS
    s = "Usage: cscript //nologo "                             'VBS
    s = s & WScript.ScriptName                                 'VBS
    s = s & " fileName [NumberOfLinesFromEnd]"                 'VBS
    WScript.Echo s                                             'VBS
    WScript.Quit                                               'VBS
  End If                                                       'VBS
  '
  ' Get the arguments: fileName and tailLines
  fileName=WScript.Arguments.Unnamed(0)                        'VBS
  If WScript.Arguments.Count > 1 Then                          'VBS
    tailLines = CLng(WScript.Arguments.Unnamed(1))             'VBS
  Else                                                         'VBS
    tailLines = 10                                             'VBS
  End If                                                       'VBS
  '
  ' Check that the file exists
  Set FSO=CreateObject("Scripting.FileSystemObject")           'VBS
  if not FSO.FileExists(fileName)  Then                        'VBS
    WScript.Echo "File " & fileName & " Not Found"             'VBS
    WScript.Quit                                               'VBS
  End If                                                       'VBS
  '
  ' Calculate the number of lines
  Set f = FSO.OpenTextFile(fileName, ForReading, True)         'VBS
  n = 0                                                        'VBS
  Do While Not f.AtEndOfStream                                 'VBS
    n = n + 1                                                  'VBS
    s = f.ReadLine                                             'VBS
  Loop                                                         'VBS
  '
  ' Output the tail part of the file
  Set f = FSO.OpenTextFile(fileName, ForReading, True)         'VBS
  i = 0                                                        'VBS
  Do While Not f.AtEndOfStream                                 'VBS
    i = i + 1                                                  'VBS
    s = f.ReadLine                                             'VBS
    If i > n - tailLines Then WScript.Echo s                   'VBS
  Loop                                                         'VBS

The output will be
  C:\_D\TEMP>cmdfaq
  This is line 10
  This is line 11
  This is line 12

What about the other way round? Present all but the first two lines
of a text file:
  @echo off & setlocal enableextensions
  for %%r in (1 2 3 4) do echo line %%r>>myfile.txt
  echo.>>myfile.txt
  for %%r in (6 7 8 9) do echo line %%r>>myfile.txt
  ::
  more /e +2 myfile.txt
  ::
  for %%f in (myfile.txt) do del %%f
  endlocal & goto :EOF
The output will be
  C:\_D\TEMP>cmdfaq
  line 3
  line 4

  line 6
  line 7
  line 8
  line 9

References/Comments:
 http://www.google.com/groups?selm=d5tcr5%2411eu%241%40agate.berkeley.edu
 http://www.google.com/groups?selm=427dc26a%240%246753%24ed2619ec%40ptn-nntp-reader01.plus.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:10 2008
Subject: 70) Calendar elements: What weekday was December 31, 2004?
Date: Thu,  6 Mar 2008 01:01:10
From: ts@uwasa.fi (Timo Salmi)

A Visual Basic Script (VBScript) aided command line script solution:
  @echo off & setlocal enableextensions
  if not exist c:\mytemp mkdir c:\mytemp
  echo>c:\mytemp\tmp$$$.vbs WScript.Echo WeekDayName(Weekday(DateValue("December 31, 2004")),true)
  for /f %%d in ('cscript //nologo c:\mytemp\tmp$$$.vbs') do set wd_=%%d
  for %%f in (c:\mytemp\tmp$$$.vbs) do if exist %%f del %%f
  rmdir c:\mytemp
  echo Weekday on December 31, 2004 is wd_=%wd_%
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  Weekday on December 31, 2004 is wd_=Fri

Likewise:
  @echo off & setlocal enableextensions
  if not exist c:\mytemp mkdir c:\mytemp
  echo>c:\mytemp\tmp$$$.vbs WScript.Echo DatePart("y",DateValue("December 31, 2004"))
  for /f %%d in ('cscript //nologo c:\mytemp\tmp$$$.vbs') do set dn_=%%d
  for %%f in (c:\mytemp\tmp$$$.vbs) do if exist %%f del %%f
  rmdir c:\mytemp
  echo The ordinal number day of year on December 31, 2004 is dn_=%dn_%
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  The ordinal number day of year on December 31, 2004 is dn_=366

Further information:
  @echo off & setlocal enableextensions
  if not exist c:\mytemp mkdir c:\mytemp
  echo>c:\mytemp\tmp$$$.vbs WScript.Echo DatePart("ww",DateValue("December 31, 2004"),vbMonday,vbFirstFourDays)
  for /f %%w in ('cscript //nologo c:\mytemp\tmp$$$.vbs') do set wn_=%%w
  for %%f in (c:\mytemp\tmp$$$.vbs) do if exist %%f del %%f
  rmdir c:\mytemp
  echo The week number on December 31, 2004 is wn_=%wn_%
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  The week number on December 31, 2004 is wn_=53

Words of caution about the week number from Dr. John Stockton are in
order. "One cannot trust software of US origin to attempt the ISO
week number, nor to get it right when they do. An ISO 8601 week
number routine needs to return both week and year; both 2004-12-27
and 2005-01-02 will be in Week 2004-53; Week 2004-01 was 2003-12-29
to 2004-01-04. ... Most Americans, AIUI, will want some other
definition entirely. ... The potential users should do a
comprehensive test on their own systems to ensure that the results
given are always correct according to the week number system that
their bosses expect/need.  One should really test Weeks 1, 52 [53]
for all 14 possible year types (leap/non-Leap, starting Mon-Sun)."

Finally, how many days are there in a month?
  @echo off & setlocal enableextensions
  :: Build a Visual Basic Script
  if not exist c:\mytemp mkdir c:\mytemp
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  ::
  :: Assume a local date format dd.mm.yyyy
  :: Customize, if necessary
  set month_=2
  set year_=2004
  ::
  :: Run the VBS script with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs
  call c:\mytemp\tmp$$$.cmd
  echo %mmdays_% days in %month_%.%year_%
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  Const ForReading = 1, ForWriting = 2, ForAppending = 8 'VBS
  Dim MyDate, mm, yyyy, DaysInMonth, fout, FSO 'VBS
  '
  Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
  mm=WshShell.ExpandEnvironmentStrings("%month_%") 'VBS
  yyyy=WshShell.ExpandEnvironmentStrings("%year_%") 'VBS
  '
  For i = 28 to 32 'VBS
    Mydate = CStr(i) & "." & CStr(mm) & "." & CStr(yyyy) 'VBS
    If (IsDate(MyDate)) Then 'VBS
      DaysInMonth = i 'VBS
    End If 'VBS
  Next 'VBS
  '
  Set FSO = CreateObject("Scripting.FileSystemObject") 'VBS
  Set fout = FSO.OpenTextFile("c:\mytemp\tmp$$$.cmd", ForWriting, true) 'VBS
  fout.WriteLine "@set mmdays_=" & DaysInMonth 'VBS
  fout.Close 'VBS
The output will be
  D:\TEST>cmdfaq
  29 days in 2.2004

A comment from Dr John Stockton in
http://groups.google.com/groups?selm=3y4RQEGxmaeEFw%2Br%40merlyn.demon.co.uk
  DaysInMonth = Day(DateSerial(yyyy, mm+1, 0)) ' VBS seems simpler

Let's get back to the original problem of getting the weekday. The
problem can also be solved with pure script commands as follows:
(Also see DATEINFO.CMD)
  @echo off & setlocal enableextensions disabledelayedexpansion
  if "%~3"=="" (
    echo Usage: %~0 DD MM YYYY
    echo No leading zeros!
    goto :EOF)
  ::
  set dd_=%~1
  set mm_=%~2
  set yyyy_=%~3
  ::
  set /a a_=(14-%mm_%)/12
  set /a y_=%yyyy_%-%a_%
  set /a m_=%mm_%+12*%a_%-2
  set /a wdnum_=1+(%dd_%+%y_%+%y_%/4-%y_%/100+%y_%/400+(31*%m_%)/12)%%7
  ::
  echo %dd_% %mm_% %yyyy_%
  for /f "tokens=%wdnum_%" %%d in (
    'echo Sun Mon Tue Wed Thu Fri Sat') do set wd_=%%d
  echo %wd_%
  endlocal & goto :EOF
The output could be e.g.
  C:\_D\TEST>cmdfaq 31 12 2004
  31 12 2004
  Fri

References/Comments:
 http://www.tondering.dk/claus/cal/node3.html#SECTION00350000000000000000
 http://www.google.com/groups?selm=45d81543%240%2424600%249b536df3%40news.fv.fi
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:11 2008
Subject: 71) How can I reboot my computer from a command line script?
Date: Thu,  6 Mar 2008 01:01:11
From: ts@uwasa.fi (Timo Salmi)

Warmboot in the old MS-DOS terminology. In XP this is really simple.
  @echo off
  shutdown -r

Or, a bit more fully
  @echo off & setlocal enableextensions
  set /p ask_=Restart, are you sure [y/N]?
  if /i not "%ask_%"=="y" if /i not "%ask_%"=="yes" goto :EOF
  @shutdown -r -f -c "Shutting down and restarting from a command line script"
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:12 2008
Subject: 72) Is it possible to use quotes as delims in for loops?
Date: Thu,  6 Mar 2008 01:01:12
From: ts@uwasa.fi (Timo Salmi)

The default delimiter set of delims in a FOR /F loop is space and
tab. That can be replaced by defining delims=xxx as the delimiter
set. Assume that we have a data file "myfile.txt"
Line,1,Part,1
Line,2,Part,1
Line,3,Part,1
Line,4,Part,1

Line,6,Part,2
Line,7,Part,2
Line,8,Part,2
Line,9,Part,2

Then
  @echo off & setlocal enableextensions
  for /f "tokens=2,4 delims=," %%a in ('type myfile.txt') do (
    echo %%a %%b)
  endlocal & goto :EOF
will result in
  1 1
  2 1
  3 1
  4 1
  6 2
  7 2
  8 2
  9 2
(The empty line is omitted).

Now, what if instead we had for some strange reason
  Line"1"Part"1
  Line"2"Part"1
  Line"3"Part"1
  Line"4"Part"1

  Line"6"Part"2
  Line"7"Part"2
  Line"8"Part"2
  Line"9"Part"2

Then we would have to take the following steps, first replacing the
quotes (") e.g. with commas (,)
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make an auxiliary temporary folder
  if not exist c:\mytemp mkdir c:\mytemp
  ::
  :: Make sure that the auxiliary file will be build up from scratch
  del c:\mytemp\tmp$$$.txt > nul 2>&1
  ::
  :: Echo each line substituting quotes with commas
  for /f "tokens=*" %%c in ('type myfile.txt') do (
    set lineContents=%%c
    echo !lineContents:"=,!
    )>>c:\mytemp\tmp$$$.txt
  ::
  :: Echo the second and the fourth token on each line
  for /f "tokens=2,4 delims=," %%a in ('type c:\mytemp\tmp$$$.txt') do (
    echo %%a %%b)
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.txt) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
This will, again, result in
  1 1
  2 1
  3 1
  4 1
  6 2
  7 2
  8 2
  9 2
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:13 2008
Subject: 73) How can I convert a hexadecimal string into an ASCII string?
Date: Thu,  6 Mar 2008 01:01:13
From: ts@uwasa.fi (Timo Salmi)

A Visual Basic Script (VBScript) aided command line script solution:
  @echo off & setlocal enableextensions
  ::
  set HexString=48 65 6C 6C 6F 20 77 6F 72 6C 64 21
  ::
  :: Build a Visual Basic Script
  if not exist c:\mytemp mkdir c:\mytemp
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs>c:\mytemp\tmp$$$.cmd
  ::
  :: Call the CMD script made by the VBS script
  call c:\mytemp\tmp$$$.cmd
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.cmd c:\mytemp\tmp$$$.vbs) do del %%f
  rmdir c:\mytemp
  ::
  :: Show the result
  echo %HexString%
  echo %AsciiString%
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  Dim MyHexString 'VBS
  Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
  MyHexString=WshShell.ExpandEnvironmentStrings("%HexString%") 'VBS
  WScript.Echo "@set AsciiString=" & HexStringToAsciiString(MyHexString) 'VBS
  '
  Function HexStringToAsciiString(HexStr) 'VBS
    For i = 1 To Int(Len(HexStr)/3)+1 'VBS
      str1 = str1 & Chr("&H" & Mid(HexStr,3*i-2,2)) 'VBS
    Next 'VBS
    HexStringToAsciiString=str1 'VBS
  End Function 'VBS
The output will be
  D:\TEST>cmdfaq
  48 65 6C 6C 6F 20 77 6F 72 6C 64 21
  Hello world!
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:14 2008
Subject: 74) How can I compare two numbers that have decimals with IF?
Date: Thu,  6 Mar 2008 01:01:14
From: ts@uwasa.fi (Timo Salmi)

A straight comparison of two decimal numbers will not work reliably,
since they are interpreted and compared as strings because the
decimal point makes the number in fact a string. Consider the
following code, which will _not_ produce wanted results.
  @echo off & setlocal enableextensions
  set number1=7.2
  set number2=-7.3
  ::
  :: Give the result
  if %number1% EQU %number2% (
    echo %number1% is equal to %number2%
    ) else (
    if %number1% GTR %number2% (
      echo %number1% is greater than %number2%
      ) else (
      echo %number1% is smaller than %number2%
    )
  )
  endlocal & goto :EOF
The output will, undesirably be
  D:\TEST>cmdfaq
  7.2 is smaller than -7.3

Instead, the following script will first convert the decimals into
integers for the comparison
  @echo off & setlocal enableextensions
  ::
  :: Get the numbers, one way or another
  if not [%2]==[] (
    set number1=%1
    set number2=%2
    ) else (
    echo Usage: %~f0 number1 number2
    endlocal & goto :EOF
    )
  ::
  :: See to it that the numbers have at least four decimal places
  call :Add4Decimals %number1% numb1
  call :Add4Decimals %number2% numb2
  ::
  :: Get the integer part and _exactly_ four decimals of the numbers
  call :ParseNumber %numb1% fix1 dec1
  call :ParseNumber %numb2% fix2 dec2
  ::
  :: Build up the numbers to be compared
  set /a n1=%fix1%%dec1%
  set /a n2=%fix2%%dec2%
  echo "Debugging" information: Comparing in fact
  echo %fix1%%dec1% and %fix2%%dec2%
  ::
  :: Give the result
  if %n1% EQU %n2% (
    echo %number1% is equal to %number2%
    ) else (
    if %n1% GTR %n2% (
      echo %number1% is greater than %number2%
      ) else (
      echo %number1% is smaller than %number2%
    )
  )
  endlocal & goto :EOF
  ::
  :: =============================================
  :Add4Decimals
  setlocal enableextensions enabledelayedexpansion
  echo %1|find ".">nul
  if %errorlevel% EQU 1 (
    endlocal& set %2=%1.0000&goto :EOF
    ) else (
    endlocal& set %2=%10000&goto :EOF)
  ::
  :: =============================================
  :ParseNumber
  setlocal enableextensions enabledelayedexpansion
  for /f "tokens=1,2 delims=." %%m in ('echo %1') do (
    set fix=%%m
    set dec=%%n)
  set dec=%dec:~0,4%
  endlocal& set %2=%fix%& set %3=%dec%& goto :EOF
The output will be
  D:\TEST>cmdfaq 7.2 -7.3
  "Debugging" information: Comparing in fact
  72000 and -73000
  7.2 is greater than -7.3

A Visual Basic Script (VBScript) aided command line script solution:
  @echo off & setlocal enableextensions
  ::
  :: Get the numbers, one way or another
  set number1=7.2
  set number2=-7.3
  ::
  :: Build a Visual Basic Script
  if not exist c:\mytemp mkdir c:\mytemp
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  ::
  :: Run the VBS script with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs>c:\mytemp\tmp$$$.cmd
  ::
  :: Call the CMD.EXE script created by the above redirection
  call c:\mytemp\tmp$$$.cmd
  ::
  :: Show and interpret the results
  echo Testing: %number1% %number2% %sign%
  if %sign% EQU 0 (
    echo %number1% is equal to %number2%
    ) else (
    if %sign% EQU 1 (
      echo %number1% is greater than %number2%
      ) else (
      echo %number1% is smaller than %number2%
    )
  )
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
  n1=WshShell.ExpandEnvironmentStrings("%number1%") 'VBS
  n2=WshShell.ExpandEnvironmentStrings("%number2%") 'VBS
  WScript.StdOut.WriteLine "@set sign=" & Sgn(n1-n2) 'VBS
The output will be
  D:\TEST>cmdfaq
  Testing: 7.2 -7.3 1
  7.2 is greater than -7.3

A G(nu)AWK aided solution
  @echo off & setlocal enableextensions
  ::
  :: Get the numbers, one way or another
  set number1=7.2
  set number2=-7.3
  ::
  :: Build a GnuAWK program file
  if not exist c:\mytemp mkdir c:\mytemp
  > c:\mytemp\tmp$$$.awk echo BEGIN{
  >>c:\mytemp\tmp$$$.awk echo if ^(^(%number1%^)-^(%number2%^)==0^) sgn=0
  >>c:\mytemp\tmp$$$.awk echo else if ^(index^(^(%number1%^)-^(%number2%^),"-"^)^) sgn=-1
  >>c:\mytemp\tmp$$$.awk echo else sgn=1
  >>c:\mytemp\tmp$$$.awk echo printf "@set sign=%%s\n",sgn
  >>c:\mytemp\tmp$$$.awk echo }
  ::
  :: Execute
  gawk -f c:\mytemp\tmp$$$.awk>c:\mytemp\tmp$$$.cmd
  call c:\mytemp\tmp$$$.cmd
  ::
  :: Show and interpret the results
  echo Testing: %number1% %number2% %sign%
  if %sign% EQU 0 (
    echo %number1% is equal to %number2%
    ) else (
    if %sign% EQU 1 (
      echo %number1% is greater than %number2%
      ) else (
      echo %number1% is smaller than %number2%
    )
  )
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.awk c:\mytemp\tmp$$$.cmd) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
The output will again be
  D:\TEST>cmdfaq
  Testing: 7.2 -7.3 1
  7.2 is greater than -7.3
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:15 2008
Subject: 75) How do I detect if an object is a file or a folder?
Date: Thu,  6 Mar 2008 01:01:15
From: ts@uwasa.fi (Timo Salmi)

A command-line script only solution based on a Usenet news posting
by Ted Davis
  @echo off & setlocal enableextensions
  if [%1]==[] (set object=NoPara & goto _echo)
  if not exist %1 (
    set object=notfound
    ) else (
    set object=folder
    dir %1 | find "<DIR>" > nul
    if errorlevel 1 set object=file)
  :_echo
  echo The object is a %object%
  endlocal & goto :EOF

A more complicated Visual Basic Script (VBScript) aided command line
script solution:
  @echo off & setlocal enableextensions
  ::
  :: Get the nameobject to be checked
  set FName_=%~1
  if "%FName_%"=="" (
    echo.
    echo Usage: %~f0 FName
    goto :EOF
  )
  if not [%2]==[] (
    echo.
    echo Long file names must be in parentheses ^(^"^)
    goto :EOF
  )
  ::
  :: Test the traditional way to see that the difference between
  :: a file and a folder is not detected
  if not exist "%FName_%" (
    echo "%FName_%" not found
    ) else (
    echo "%FName_%" found)
  ::
  :: Build a Visual Basic Script
  if not exist c:\mytemp mkdir c:\mytemp
  findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
  ::
  :: Run it with Microsoft Windows Script Host Version 5.6
  cscript //nologo c:\mytemp\tmp$$$.vbs>c:\mytemp\tmp$$$.cmd
  ::
  :: Call the CMD script made my the VBS script
  call c:\mytemp\tmp$$$.cmd
  ::
  :: Show the results
  echo %FName_% %FNameStatus%
  ::
  :: Clean up
  for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do del %%f
  rmdir c:\mytemp
  endlocal & goto :EOF
  '
  '................................................................
  'The Visual Basic Script
  '
  Dim FSO, f                                                     'VBS
  Set WshShell = WScript.CreateObject("WScript.shell")           'VBS
  FName=WshShell.ExpandEnvironmentStrings("%FName_%")            'VBS
  '                                                              'VBS
  Set FSO=CreateObject("Scripting.FileSystemObject")             'VBS
  If not (FSO.FileExists(FName) or FSO.FolderExists(FName)) Then 'VBS
    WScript.Echo "@set FNameStatus=NotFound"                     'VBS
    WScript.Quit                                                 'VBS
  End If                                                         'VBS
  If FSO.FileExists(FName) Then                                  'VBS
    Set f = FSO.GetFile(FName)                                   'VBS
  End if                                                         'VBS
  If FSO.FolderExists(FName) Then                                'VBS
    Set f = FSO.GetFolder(FName)                                 'VBS
  End if                                                         'VBS
  If (f.attributes and 16) Then                                  'VBS
    WScript.Echo "@set FNameStatus=Folder"                       'VBS
  Else                                                           'VBS
    WScript.Echo "@set FNameStatus=File"                         'VBS
  End If                                                         'VBS

However, maybe the simplest method is
  @echo off & setlocal enableextensions
  if "%~1"=="" (
    echo Usage: %~0 [FileOrFolderName]
    goto :EOF
    )
  ::
  if not exist "%~1" (
    echo File or folder "%~1" not found
    goto :EOF
    )
  if exist "%~1\" (
    echo "%~1" is a folder
    ) else (
    echo "%~1" is a file
    )
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=c2uroi%24pvs%2406%241%40news.t-online.com
 http://www.google.com/groups?selm=O4huX7rRGHA.424%40TK2MSFTNGP12.phx.gbl
 http://www.google.com/groups?selm=ehQOtBsRGHA.5656%40TK2MSFTNGP11.phx.gbl
 http://www.google.com/groups?selm=1166068807.744364.293490%4073g2000cwn.googlegroups.com

Alternative (note, omits deleting the temporary vbs):
 http://www.jsifaq.com/SF/Tips/Tip.aspx?id=10229
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:16 2008
Subject: 76) How do I create an empty file? How can I detect the empty files?
Date: Thu,  6 Mar 2008 01:01:16
From: ts@uwasa.fi (Timo Salmi)

Creating an empty file:
  if not exist empty.txt copy nul empty.txt

Detecting empty files in a folder:
  @echo off & setlocal enableextensions
  for %%f in (d:\test\*.*) do (
    if %%~zf EQU 0 echo %%~tf %%~zf "%%~ff"
    )
  endlocal & goto :EOF

And throughout an entire drive
  @echo off & setlocal enableextensions
  for /f "tokens=*" %%f in ('dir /b/s/a-d d:\*.*') do (
    if %%~zf EQU 0 echo %%~tf %%~zf %%~ff
    )
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:17 2008
Subject: 77) How do I list the files in \All Users\Desktop in the short format?
Date: Thu,  6 Mar 2008 01:01:17
From: ts@uwasa.fi (Timo Salmi)

The user wishes to get a short format (8+3) directory listing of the
files say, in the "\All Users\Desktop" directory. How does one do
that?

There is no immediate DIR switch to do that. A brief round-about way
is the one below. It omits directory entries, hidden and system
files. The date, size, and the short-format name of the files are
given. It is easily customized.

  @echo off & setlocal enableextensions
  for /f "tokens=*" %%f in (
    'dir C:\*.* /a:-d-h-s/b/s ^|find "\All Users\Desktop"') do (
      echo %%~tzsf)
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:18 2008
Subject: 78) Is it possible automatically to record my logon times into a file?
Date: Thu,  6 Mar 2008 01:01:18
From: ts@uwasa.fi (Timo Salmi)

This is reasonably simple. You'll need the following kind of a
script:
  @echo off & setlocal enableextensions
  echo Logon: %USERNAME% %COMPUTERNAME% %date% %time%>>C:\wherever\logon.txt
  endlocal & goto :EOF
Then
 Right-click the "start" in the lower left corner
  Choose "open"
   Choose the "Programs" folder
    Choose the "Startup" forlder. Create if need be.
     Click "File" in the upper left toolbar
      Click "New"
       Click "Shortcut"
        In the Wizard browse to your script
That's it. Next time you reboot, there will be an entry in your log.

If you wish to reverse the timeline, that is to have the lastest
entry on top, then e.g.
  @echo off & setlocal enableextensions
  if not defined temp goto :EOF
  echo Logon: %USERNAME% %COMPUTERNAME% %date% %time%>"%temp%\logon1.tmp"
  set target_=C:\logon.txt
  if not exist "%target_%" (
    copy /y "%temp%\logon1.tmp" "%target_%" > nul
    goto _out
    )
  copy "%target_%" "%temp%\logon2.tmp" > nul
  copy /y "%temp%\logon1.tmp" + "%temp%\logon2.tmp" "%target_%" > nul
  :_out
  for %%f in ("%temp%\logon1.tmp" "%temp%\logon2.tmp") do if exist %%f del %%f
  endlocal & goto :EOF
Customize the destination of the log file C:\logon.txt if you do not
have write permissions to the root directory of drive C:.
The logon.txt file might look someting like
 Logon: ts GARFIELD 26.10.2004 10:36:11.13
 Logon: ts GARFIELD 25.10.2004  8:33:36.79
 Logon: ts GARFIELD 24.10.2004  9:12:31.65

A sideline. The above assumes that there are no spaces in the %temp%
path. It is customary to use the 8+3 format for the temp variable to
avoid complications with spaces. E.g. one might have temp as
C:\DOCUME~1\user\LOCALS~1\Temp

Incidentally, how does one permanently set an environment variable
value in XP?
 Right click: My Computer
 Choose Properties
 Choose Advanced
 Click "Environment Variables"
 For User variables click New
 Define Variable Value

What likewise about logout? See item #71. Just add
  echo Logout: %USERNAME% %COMPUTERNAME% %date% %time%>>C:\wherever\logon.txt
before the shutdown line.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:19 2008
Subject: 79) How can I trim leading and trailing spaces?
Date: Thu,  6 Mar 2008 01:01:19
From: ts@uwasa.fi (Timo Salmi)

If it is about a file, here is a demonstration
  @echo off & setlocal enableextensions
  echo  This  is  a  test   >MyTest.txt
  echo    Second  line     >>MyTest.txt
  <Mytest.txt sed -e "s/^ *//" -e "s/ *\.$//"
  del Mytest.txt
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  This  is  a  test
  Second  line

Or, with a pure script, provided there are no backslashes (\)
  @echo off & setlocal enableextensions enabledelayedexpansion
  set debug=.
  echo  This  is  a  test   >MyTest.txt
  echo    Second  line     >>MyTest.txt
  for /f "tokens=* delims= " %%a in ('type Mytest.txt') do (
    set s_=%%~na
    echo !s_!%debug%
    )
  del Mytest.txt
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
  This  is  a  test.
  Second  line.

If it is about an environment variable:
  @echo off & setlocal enableextensions
  set S=  This  is  a  test
  echo %S%.
  echo %S%|sed -e "s/^ *//" -e "s/ *$//" -e "s/^/@set S=&/">"%temp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%temp%\tmp$$$.cmd"
  echo %S%.
  endlocal & goto :EOF

The output will be
  D:\TEST>cmdfaq
    This  is  a  test     .
  This  is  a  test.

Or, with a pure script
  @echo off & setlocal enableextensions
  rem enabledelayedexpansion
  set S=  This  is  a  test
  echo %S%.
  for /f "tokens=* delims= " %%a in ('echo %S%') do set S=%%a
  echo %S%.
  endlocal & goto :EOF

Note, however, that the output will be a different:
  D:\TEST>cmdfaq
    This  is  a  test     .
  This is a test .

Likewise, one can drop the _leading_ zeros:
  @echo off & setlocal enableextensions
  set num=0800
  for /f "tokens=* delims=0" %%a in ('echo %num%') do set num=%%a
  echo %num%
  endlocal & goto :EOF
The output will be
  C:\_D\BAS>cmdfaq
  800

References/Comments:
 http://www.google.com/groups?selm=26D08E3E-0C2D-4E38-84BA-7E9B37651B76%40microsoft.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:20 2008
Subject: 80) How can I extract the last part of a path such as C:\ABC\DEF\GHI\?
Date: Thu,  6 Mar 2008 01:01:20
From: ts@uwasa.fi (Timo Salmi)

The core of question as posed on the Usenet news is
  >"C:\ABX\XYZ\"     would return "XYZ"
  >"C:\ABC\DEF\GHI\" would return "GHI"

There are several solutions. First with SED and GAWK. But before
reading on, you may wish to revisit the previous item #79.
  @echo off & setlocal enableextensions
  set mystr=C:\ABC\DEF XYZ\GHI\
  echo %mystr%|sed -e "s/\\*$//"|gawk -F\ '{printf "@set last=%%s\n",$NF}'>"%temp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%temp%\tmp$$$.cmd"
  echo %mystr%
  echo %last%
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  C:\ABC\DEF XYZ\GHI\
  GHI

Next let's take a step by step enhancements as often happens with
questions that have arisen when discussion has continues on the
Usenet news about a particular problem.

Second solution, with pure script in a slow, generic fashion
  @echo off & setlocal enableextensions enabledelayedexpansion
  set mystr=C:\ABC\DEF XYZ\GHI\
  echo %mystr%
  :: Remove the last character
  set mystr=%mystr:~0,-1%
  echo %mystr%
  :: Get the position of the last \
  call :InstrLastFN "%mystr%" "\\" pos
  set /a pos +=1
  :: Get the desired substring
  set result=!mystr:~%pos%!
  rem echo %result%
  for %%a in ("%mystr%") do echo %%~na
  endlocal & goto :EOF
  ::
  :: ============================================================
  :InstrLastFN
  setlocal enableextensions enabledelayedexpansion
  echo %1|findstr %2>nul
  if %errorlevel% EQU 1 (endlocal & set %3=-1& goto :EOF)
  set rest_=%1
  set /a instr_=-1
  :_loop
    set rest_=%rest_:~1%
    echo !rest_!|findstr %2>nul
    if %errorlevel% EQU 1 (endlocal & set %3=%instr_%& goto :EOF)
    set /a instr_ +=1
    goto _loop
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  C:\ABC\DEF XYZ\GHI\
  C:\ABC\DEF XYZ\GHI
  GHI

The neatest solution is adapted from a posting by Phil Robyn.
  @echo off & setlocal enableextensions enabledelayedexpansion
  set mystr=C:\ABC\DEF XYZ\GHI\
  echo %mystr%
  set mystr=%mystr:~0,-1%
  echo %mystr%
  for %%a in ("%mystr%") do echo %%~na
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  C:\ABC\DEF XYZ\GHI\
  C:\ABC\DEF XYZ\GHI
  GHI

Even that solution can be enhanced as pointed out on the Usenet
news. The first trick (%%~fa) is to ensure that a potential trailing
\ is removed without disturbing the string if the \ is not there.
The second trick (%%~nxa) is ensuring that a critically placed,
potential dot (.) in the string is not dropped. See the References
for more, and the originators.
  @echo off & setlocal enableextensions
  set debug=true
  set mystr=C:\ABC\DEF XYZ\.GHI\
  for %%a in ("%mystr%\") do set mystr=%%~fa
  if defined debug echo %mystr%
  set mystr=%mystr:~0,-1%
  if defined debug echo %mystr%
  for %%a in ("%mystr%") do set mystr=%%~nxa
  if defined debug echo %mystr%
  endlocal & goto :EOF
The output will be
  D:\TEST>cmdfaq
  C:\ABC\DEF XYZ\.GHI\
  C:\ABC\DEF XYZ\.GHI
  .GHI
In the old days when the proverbial "we" programmed in straight
MS-DOS batch we relied a lot on the peculiarities of the DOS batch
syntax. When the versions changed, some of the tricks no longer
worked. The above has some resemblance in the sense that it assumes
that the %~fa trick will stay. A nice and an inventive solution,
nevertheless.

A more generic option to handle the trailing bakcslash \ is
  @echo off & setlocal enableextensions
  set debug=true
  set mystr=C:\ABC\\DEF XYZ\.GHI\
  if defined debug echo %mystr%
  set mystr=%mystr%\
  if defined debug echo %mystr%
  set mystr=%mystr:\\=\%
  if defined debug echo %mystr%
  set mystr=%mystr:~0,-1%
  if defined debug echo %mystr%
  for %%a in ("%mystr%") do set mystr=%%~nxa
  if defined debug echo %mystr%
  endlocal & goto :EOF
producting the following output
  D:\TEST>cmdfaq
  C:\ABC\\DEF XYZ\.GHI\
  C:\ABC\\DEF XYZ\.GHI\\
  C:\ABC\DEF XYZ\.GHI\
  C:\ABC\DEF XYZ\.GHI
  .GHI

Another demonstration
  @echo off & setlocal enableextensions disabledelayedexpansion
  :: Get the string to be parsed
  set MyArguments=%~1
  if "%~1"=="" set MyArguments=d:\folder 1\folder 2\folder 3\
  echo MyArguments=%MyArguments%
  ::
  :: Get the first part and the rest of a variable
  for /f "tokens=1,* delims=\" %%a in ("%MyArguments%") do (
    set first_=%%a
    set rest_=%%b
    )
  echo first_=%first_%
  echo rest_ =%rest_%
  ::
  :: Get the last part of a variable
  set rest_=%MyArguments%
  :_loop
  for /f "tokens=1,* delims=\" %%a in ("%rest_%") do (
    set rest_=%%b
    set last_=%%a
    if defined rest_ goto _loop
    )
  echo last_=%last_%
  endlocal & goto :EOF

The output:
  C:\_D\BAS>cmdfaq
  MyArguments=d:\folder 1\folder 2\folder 3\
  first_=d:
  rest_ =folder 1\folder 2\folder 3\
  last_=folder 3

Also see the item
 144} How do I parse the items from a path like C:\a\b\c\d ?

References/Comments:
 http://www.google.com/groups?selm=1104461083.217256.292420%40z14g2000cwz.googlegroups.com
 http://www.google.com/groups?selm=cr277b%24gg8%2400%241%40news.t-online.com
 http://www.google.com/groups?selm=NJkBd.657015%24%k.480801%40pd7tw2no
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:21 2008
Subject: 81) Is there a script to capitalize all the words in a text file?
Date: Thu,  6 Mar 2008 01:01:21
From: ts@uwasa.fi (Timo Salmi)

 Q: "I need a batch file that will change the first letter in every
word in a text file to upper case."

 A: Using sed
  @echo off & setlocal enableextensions
  if not defined mytemp set mytemp=%temp%
  echo s/ a/ A/g>  %mytemp%\sedcmd.tmp
  echo s/ b/ B/g>> %mytemp%\sedcmd.tmp
  echo s/ c/ C/g>> %mytemp%\sedcmd.tmp
  echo s/ d/ D/g>> %mytemp%\sedcmd.tmp
  echo s/ e/ E/g>> %mytemp%\sedcmd.tmp
  echo s/ f/ F/g>> %mytemp%\sedcmd.tmp
  echo s/ g/ G/g>> %mytemp%\sedcmd.tmp
  echo s/ h/ H/g>> %mytemp%\sedcmd.tmp
  echo s/ i/ I/g>> %mytemp%\sedcmd.tmp
  echo s/ j/ J/g>> %mytemp%\sedcmd.tmp
  echo s/ k/ K/g>> %mytemp%\sedcmd.tmp
  echo s/ l/ L/g>> %mytemp%\sedcmd.tmp
  echo s/ m/ M/g>> %mytemp%\sedcmd.tmp
  echo s/ n/ N/g>> %mytemp%\sedcmd.tmp
  echo s/ o/ O/g>> %mytemp%\sedcmd.tmp
  echo s/ p/ P/g>> %mytemp%\sedcmd.tmp
  echo s/ q/ Q/g>> %mytemp%\sedcmd.tmp
  echo s/ r/ R/g>> %mytemp%\sedcmd.tmp
  echo s/ s/ S/g>> %mytemp%\sedcmd.tmp
  echo s/ t/ T/g>> %mytemp%\sedcmd.tmp
  echo s/ u/ U/g>> %mytemp%\sedcmd.tmp
  echo s/ v/ V/g>> %mytemp%\sedcmd.tmp
  echo s/ w/ W/g>> %mytemp%\sedcmd.tmp
  echo s/ x/ X/g>> %mytemp%\sedcmd.tmp
  echo s/ y/ Y/g>> %mytemp%\sedcmd.tmp
  echo s/ z/ Z/g>> %mytemp%\sedcmd.tmp
  rem
  echo s/^^a/A/g>> %mytemp%\sedcmd.tmp
  echo s/^^b/B/g>> %mytemp%\sedcmd.tmp
  echo s/^^c/C/g>> %mytemp%\sedcmd.tmp
  echo s/^^d/D/g>> %mytemp%\sedcmd.tmp
  echo s/^^e/E/g>> %mytemp%\sedcmd.tmp
  echo s/^^f/F/g>> %mytemp%\sedcmd.tmp
  echo s/^^g/G/g>> %mytemp%\sedcmd.tmp
  echo s/^^h/H/g>> %mytemp%\sedcmd.tmp
  echo s/^^i/I/g>> %mytemp%\sedcmd.tmp
  echo s/^^j/J/g>> %mytemp%\sedcmd.tmp
  echo s/^^k/K/g>> %mytemp%\sedcmd.tmp
  echo s/^^l/L/g>> %mytemp%\sedcmd.tmp
  echo s/^^m/M/g>> %mytemp%\sedcmd.tmp
  echo s/^^n/N/g>> %mytemp%\sedcmd.tmp
  echo s/^^o/O/g>> %mytemp%\sedcmd.tmp
  echo s/^^p/P/g>> %mytemp%\sedcmd.tmp
  echo s/^^q/Q/g>> %mytemp%\sedcmd.tmp
  echo s/^^r/R/g>> %mytemp%\sedcmd.tmp
  echo s/^^s/S/g>> %mytemp%\sedcmd.tmp
  echo s/^^t/T/g>> %mytemp%\sedcmd.tmp
  echo s/^^u/U/g>> %mytemp%\sedcmd.tmp
  echo s/^^v/V/g>> %mytemp%\sedcmd.tmp
  echo s/^^w/W/g>> %mytemp%\sedcmd.tmp
  echo s/^^x/X/g>> %mytemp%\sedcmd.tmp
  echo s/^^y/Y/g>> %mytemp%\sedcmd.tmp
  echo s/^^z/Z/g>> %mytemp%\sedcmd.tmp
  rem
  sed -f%mytemp%\sedcmd.tmp myfile.txt
  del %mytemp%\sedcmd.tmp
  endlocal & goto :EOF

What about foreign character sets? For example for the Finnish
character set add
  echo s/ / /g>> %mytemp%\sedcmd.tmp
  echo s/ / /g>> %mytemp%\sedcmd.tmp
  echo s/ / /g>> %mytemp%\sedcmd.tmp
  rem
  echo s/^^//g>> %mytemp%\sedcmd.tmp
  echo s/^^//g>> %mytemp%\sedcmd.tmp
  echo s/^^//g>> %mytemp%\sedcmd.tmp

References/Comments:
 http://www.google.com/groups?selm=41ea366b%241_2%40127.0.0.1
 http://www.google.com/groups?selm=64alu0h1rgs0csc3sa3kd737upcnve1h2m%404ax.com
 http://www.google.com/groups?selm=YSPaoRH8cq6BFwM1%40merlyn.demon.co.uk
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:22 2008
Subject: 82) Why does echo 9>temp.txt fail while echo 10>temp.txt works?
Date: Thu,  6 Mar 2008 01:01:22
From: ts@uwasa.fi (Timo Salmi)

A cmd.exe feature. The sole digit nine is taken to be a file handle
0-9 when redirection is used. You'll have to escape it e.g. applying
  @echo off
  echo ^9>temp.txt
or
  echo.9>temp.txt
or
  >temp.txt echo 9

The problem might be particularly insidious in a case like this
  @echo off & setlocal enableextensions
  set var_=9
  echo %var_%>tmp$$$.txt
  for %%c in (type del) do call %%c tmp$$$.txt
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  ECHO is off.
That can be avoided by using
  echo ^%var_%>tmp$$$.txt
or
  echo.%var_%>tmp$$$.txt

What does one do with a file handle? Try this without having a
diskette in the drive
  @echo off
  dir a: > temp.dir
What you'll get is on the screen
  The device is not ready.
But if you would rather that the line went into the temp.dir file,
then
  @echo off
  dir a:> temp.dir 2>&1

References/Comments:
 http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:23 2008
Subject: 83) How to archive files with a rotation of five latest generations?
Date: Thu,  6 Mar 2008 01:01:23
From: ts@uwasa.fi (Timo Salmi)

> I would like to archive some files periodically but only keep the last
> five iterations. The directories would ideally have date names. I know
> how to get a date into a directory name but I'm having a bit of trouble
> trying to figure out how to delete the oldest directory.

Such a backup rotation uses moves. Below is the logic. The commands
(e.g. zipping or whatever) are easily written once the simple logic
sinks in:
 archive4 --> archive5
 archive3 --> archive4
 archive2 --> archive3
 archive1 --> archive2
 delete archive1
 Do the new archiving to archive1
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:24 2008
Subject: 84) How can I automate downloading files from an ftp-site?
Date: Thu,  6 Mar 2008 01:01:24
From: ts@uwasa.fi (Timo Salmi)

This example will get you the files
ftp://garbo.uwasa.fi/pc/link/tsbat.zip
ftp://garbo.uwasa.fi/pc/link/tscmd.zip

  @echo off & setlocal enableextensions
  echo open garbo.uwasa.fi>"%temp%\ftp$$$.tmp"
  echo anonymous>>"%temp%\ftp$$$.tmp"
  echo myid@mypc.mydomain>>"%temp%\ftp$$$.tmp"
  echo binary>>"%temp%\ftp$$$.tmp"
  echo cd /pc/link>>"%temp%\ftp$$$.tmp"
  echo literal pasv>>"%temp%\ftp$$$.tmp"
  echo lcd C:\_MyLocalDownloadsFolder>>"%temp%\ftp$$$.tmp"
  echo get tsbat.zip>>"%temp%\ftp$$$.tmp"
  echo get tscmd.zip>>"%temp%\ftp$$$.tmp"
  echo quit>>"%temp%\ftp$$$.tmp"
  ftp -s:"%temp%\ftp$$$.tmp"
  del "%temp%\ftp$$$.tmp"
  endlocal & goto :EOF

References/Comments:
 http://support.microsoft.com/kb/96269/en-us
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:25 2008
Subject: 85) How to test if a folder contains any files with long names?
Date: Thu,  6 Mar 2008 01:01:25
From: ts@uwasa.fi (Timo Salmi)

The solution below is based on the format of DIR /X /A:-D listing.
E.g. one might have

  C:\_M>DIR /X /A:-D
   Volume in drive C is WHATEVER
   Volume Serial Number is E771-A1B3

   Directory of C:\_M

  27.02.2005  21:44                24 LONGNA~1.TXT LongNameFile.txt
  27.02.2005  21:43                16              test.cmd
                 2 File(s)             40 bytes
                 0 Dir(s)  51,807,084,544 bytes free

For a long file name the relevant row contains at least five space
delimited items while the other lines only have four. Furthermore,
the folder listing's footer must be dropped.
  @echo off & setlocal enableextensions
  set lfn_=
  for /f "skip=4 tokens=4-5 delims= " %%a in (
    'dir /x /a:-d /-c "%~1" ^|findstr /v /b /c:"  "') do (
    if not [%%b]==[] if /i not [%%a]==[%%b] set lfn_=true)
  if [%lfn_%]==[] (
    echo No long file names found in folder %1
     ) ELSE (
    echo Long file names found in folder %1)
  endlocal & goto :EOF

You may wish to take a look at
 dir /?
 findstr /?|more

The method can also be used to detect the LFN-status of a single
file:
  @echo off & setlocal enableextensions
  ::
  if [%1]==[] (
    echo Usage: %~0 [FileName]
    goto :EOF)
  ::
  echo %1|findstr "[*?]">nul
  if %errorlevel% EQU 0 (
    echo %1 contains wildcards, not allowed
    goto :EOF)
  ::
  if not exist "%~1" (
    echo File %1 not found
    goto :EOF)
  ::
  dir /a:d "%~1" 2>&1 |findstr /c:"<DIR>">nul
  if %errorlevel% EQU 0 (
    echo %1 is a folder
    goto :EOF)
  ::
  set lfn_=
  for /f "skip=4 tokens=4-5 delims= " %%a in (
    'dir /x /a:-d /-c "%~1" ^|findstr /v /b /c:"  "') do (
    if not [%%b]==[] if /i not [%%a]==[%%b] set lfn_=true)
  if [%lfn_%]==[] (
    echo %1 is not a long file name
     ) ELSE (
    echo %1 is a long file name)
  endlocal & goto :EOF

There are other methods. First consider the task of getting the
short format of a filename
  @echo off & setlocal enableextensions enabledelayedexpansion
  for %%f in ("%~1") do (
    set lfn=%%~ff
    set sfn=%%~sf
    if not exist "!lfn!" (
      echo File "!lfn!" not found
      ) else (
      echo !lfn!
      echo !sfn!
      )
    )
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq "C:\_M\test 2.txt"
  C:\_M\test 2.txt
  C:\_M\TEST2~1.TXT

Drawing from the above we have
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  if "%~1"=="" (
    echo Usage %~0 [FolderName]
    goto :EOF
    )
  ::
  if not exist "%~1\" (
    echo Folder "%~1\" not found
    goto :EOF
    )
  ::
  set lfnFound=
  for %%f in ("%~1\*.*") do (
    set lfn=%%~ff
    set sfn=%%~sf
    if /i not "!lfn!"=="!sfn!" set lfnFound=true
    )
  ::
  if defined lfnFound (
    echo Long file names found in folder "%~1"
     ) ELSE (
    echo No long file names found in folder "%~1")
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq C:\_D\TEST
  Long file names found in folder "C:\_D\TEST"

References/Comments:
 http://www.google.com/groups?selm=4263b31d%241_4%40alt.athenanews.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:26 2008
Subject: 86) How to put each line of a text file into an environment variable?
Date: Thu,  6 Mar 2008 01:01:26
From: ts@uwasa.fi (Timo Salmi)

Note the use of the delayed expansion method
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make a test file
  for %%f in (myfile.txt) do if exist %%f del %%f
  for %%f in (first second third fourth) do (
    echo This is the %%f line>>myfile.txt)
  echo.>>myfile.txt
  for %%f in (sixth seventh eight) do (
    echo This is the %%f line>>myfile.txt)
  ::
  :: Do it
  set lineNro_=
  for /f "tokens=* delims=" %%r in ('type myfile.txt') do (
    set /a lineNro_+=1
    echo @set line!lineNro_!_=%%r>>"%temp%\tmp$$$.cmd")
  call %temp%\tmp$$$.cmd
  ::
  :: Display the outcome
  for /l %%v in (1,1,%lineNro_%) do echo line%%v_=!line%%v_!
  ::
  :: Clean up
  for %%f in (myfile.txt "%temp%\tmp$$$.cmd") do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  line1_=This is the first line
  line2_=This is the second line
  line3_=This is the third line
  line4_=This is the fourth line
  line5_=This is the sixth line
  line6_=This is the seventh line
  line7_=This is the eight line

Note that the empty line (the true fifth line) is skipped. Also note
that the text file should not contain the special script characters
&()[]{}^=;!'+,`~
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:27 2008
Subject: 87) How can I create a four-digit random string?
Date: Thu,  6 Mar 2008 01:01:27
From: ts@uwasa.fi (Timo Salmi)

A Visual Basic Script (VBScript) aided command line script solution:
  @echo off & setlocal enableextensions
  ::
  :: Build a Visual Basic Script and run it with Microsoft Windows Script Host
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  cscript //nologo "%temp%\tmp$$$.vbs">"%temp%\tmp$$$.cmd"
  ::
  :: Call the command line script which the script host built
  call "%temp%\tmp$$$.cmd"
  ::
  :: Display the result
  echo rand_=%rand_%
  ::
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  Randomize                                         'VBS
  MyRandom = Right("0000" & Int(10000*Rnd) , 4)     'VBS
  WScript.StdOut.WriteLine "@set rand_=" & MyRandom 'VBS
The output might be e.g.
  C:\_M>c:\_d\test\cmdfaq
  rand_=7674

One of the options is to use G(nu)AWK. The string is between 0000
and 9999. Leading zeros are added by the solution as needed.
  @echo off & setlocal enableextensions
  ::
  :: Create a random number between 0-9999
  gawk 'BEGIN{srand();printf "@set rand_=%%04d\n",int(10000*rand())}'>"%temp%\tmp$$$.cmd"
  for %%c in (call del) do %%c "%temp%\tmp$$$.cmd"
  ::
  :: Display the result
  echo rand_=%rand_%
  endlocal & goto :EOF
The output might be e.g.
  C:\_D\TEST>cmdfaq
  rand_=0857

Incidentally, if one only needs two digits one quick-and-dirty
alternative is to take the current milliseconds: %time:~9,2%

But most importantly, there is a inbuilt random generator as given
by the XP Command-line reference - Concepts - Command shell
overview: The variable %RANDOM% a random in a script will be a
decimal number between 0 and 32767.
  @echo off & setlocal enableextensions
  set /a rand_=%random% %% 10000
  set rand_=0000%rand_%
  echo %rand_:~-4%
  endlocal & goto :EOF
The output might be e.g.
  C:\_D\TEST>cmdfaq
  rand_=4823

There is a catch, however. If the output is e.g.
  rand_=0968
a prefix of 0 indicates an octal number if used in calculations.
Thus as the above would be an invalid octal number because octal
numbers cannot have the digits 8 or 9. To demonstrate
  @echo off & setlocal enableextensions
  set /a x=0968
  endlocal & goto :EOF
The output would be
  C:\_D\TEST>cmdfaq
  Invalid number.  Numeric constants are either decimal (17),
  hexadecimal (0x11), or octal (021).

Consider a slightly different task. Get random numbers from 1 to 52
without any repeats. Like shuffling a deck of cards numbered 1-52.
Using VBS-aided scripting and the shuffle algorithm to avoid any
repeats we get:
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Set the number of random numbers to be shuffled
  :: Typically 52 would be a deck of cards
  set max_=52
  ::
  :: Build a Visual Basic Script
  set vbs_=%mytemp%\tmp$$$.vbs
  findstr "'%skip%VBS" "%~f0" > %vbs_%
  ::
  :: Run it with Microsoft Windows Script Host Version 5.6
  set cmd_=%mytemp%\tmp$$$.cmd
  cscript //nologo %vbs_% > %cmd_%
  ::
  :: Call the command line script which the script host built
  call %cmd_%
  ::
  :: Display the results
  for /l %%i in (1,1,%max_%) do echo rand[%%i] = !rand[%%i]!
  ::
  :: Clean up
  for %%f in ("%vbs_%" "%cmd_%") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  '.......................................................
  'The Visual Basic Script
  '
  Dim maxItems, i, j, k, rand(1000)                     'VBS
  Set WshShell = WScript.CreateObject("WScript.shell")  'VBS
  maxItems=WshShell.ExpandEnvironmentStrings("%max_%")  'VBS
  Randomize                                             'VBS
  For i = 1 to MaxItems                                 'VBS
    rand(i) = i                                         'VBS
  Next                                                  'VBS
  For i = 1 to MaxItems                                 'VBS
    j = 1 + Int(MaxItems*rnd)                           'VBS
    k = rand(i)                                         'VBS
    rand(i) = rand(j)                                   'VBS
    rand(j) = k                                         'VBS
  Next                                                  'VBS
  For i = 1 to MaxItems                                 'VBS
    WScript.Echo "@set rand[" & i & "]=" & rand(i)      'VBS
  Next                                                  'VBS

The output would be e.g.
  C:\_D\TEST>cmdfaq
  rand[1] = 3
  rand[2] = 6
  :
  rand[50] = 36
  rand[51] = 26
  rand[52] = 40

For an instructive example of a CMD-commands-only script creating
random strings see "MAKEPASS.CMD Make a randomized password" included
in this package.

References/Comments:
 http://www.google.com/groups?selm=423ca927%240%24548%24ed2619ec%40ptn-nntp-reader03.plus.net
 http://www.google.com/groups?selm=vT8HY5CmxKPCFwPt%40merlyn.demon.co.uk
 http://www.google.com/groups?selm=426A6578.49DD09AA%40unibwm.de
 http://www.google.com/groups?selm=v8ml611d7hjkdj59rmq9j96rttk08ed7gd%404ax.com
 http://www.google.com/groups?selm=TV1oJTHTXd7DFwcy%40merlyn.demon.co.uk
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:28 2008
Subject: 88) How to convert DEC to HEX with a script file, and vice versa?
Date: Thu,  6 Mar 2008 01:01:28
From: ts@uwasa.fi (Timo Salmi)

If you want a pure script only solution, see items 32 and 33 in this
FAQ. If you want to convert a string given in hexadecimals see item
73.

This can be also done e.g. with G(nu)AWK or a Visual Basic
Script (VBScript). The gawk solutions are given below. No error
checking for the correct input format of the digits is included in
the conversion algorithms. To put the results in an environment
variable see the DEC to BIN awk and VBScript examples in this item.

  @echo off & setlocal enableextensions
  rem DEC to HEX
  ::
  :: Usage
  if "%~1"=="" (
    echo.
    echo Usage: %~f0 [DecimalNumber] to be converted to Hexadecimal
    goto :EOF)
  ::
  :: Build an awk source
  set awksrc="%temp%\tmp$$$.awk"
  >  %awksrc% echo BEGIN{
  >> %awksrc% echo number=%1
  >> %awksrc% echo base=16
  >> %awksrc% echo digit="0123456789ABCDEF"
  >> %awksrc% echo result=""
  >> %awksrc% echo while(number!=0)
  >> %awksrc% echo  {
  >> %awksrc% echo   i=number-base*int(number/base)
  >> %awksrc% echo   result=substr(digit,i+1,1)result
  >> %awksrc% echo   number=int(number/base)
  >> %awksrc% echo  }
  >> %awksrc% echo printf"%%s\n",result
  >> %awksrc% echo }
  ::
  :: Run the awk source
  gawk -f %awksrc%
  ::
  :: Clean up
  for %%f in (%awksrc%) do if exist %%f del %%f
  endlocal & goto :EOF
An example of the output
  C:\_D\TEST>cmdfaq 127
  7F
As is seen the above can be easily generalized by changing the
"base" variable. The same goes for the other cases.

In the special case of DEC to HEX gawk inbuilt features can
alternatively be used as a simple shortcut:
  @echo off & setlocal enableextensions
  rem DEC to HEX
  ::
  if [%1]==[] (
    echo.
    echo Usage: %~f0 [DecimalNumber] to be converted to Hexadecimal
    goto :EOF)
  ::
  gawk 'BEGIN{printf"%%X\n","%1"}'
  ::
  endlocal & goto :EOF

The other way round the HEX to DEC code is
  @echo off & setlocal enableextensions
  rem HEX to DEC
  ::
  :: Usage
  if "%~1"=="" (
    echo.
    echo Usage: %~f0 [HexNumber] to be converted to Decimal
    goto :EOF)
  ::
  :: Build an awk source
  set awksrc="%temp%\tmp$$$.awk"
  >  %awksrc% echo BEGIN{
  >> %awksrc% echo k=1
  >> %awksrc% echo d=0
  >> %awksrc% echo base=16
  >> %awksrc% echo number=toupper("%1")
  >> %awksrc% echo i=length(number)+1
  >> %awksrc% echo while(i!=1)
  >> %awksrc% echo  {
  >> %awksrc% echo   i--
  >> %awksrc% echo   j=index("123456789ABCDEF",substr(number,i,1))
  >> %awksrc% echo   d=d+j*k
  >> %awksrc% echo   k=base*k
  >> %awksrc% echo  }
  >> %awksrc% echo printf"%%s in HEX is %%s in DEC\n",number,d
  >> %awksrc% echo }
  ::
  :: Run the awk source
  gawk -f %awksrc%
  ::
  :: Clean up
  for %%f in (%awksrc%) do if exist %%f del %%f
  endlocal & goto :EOF
An example of the output
  C:\_D\TEST>cmdfaq FD
  FD in HEX is 253 in DEC

Let's consider the conversion from decimal to binary and putting the
result into an environment variable.
  @echo off & setlocal enableextensions
  rem DEC to BIN
  ::
  :: Usage
  if "%~1"=="" (
    echo.
    echo Usage: %~f0 [DecimalNumber] to be converted to Binary
    goto :EOF)
  ::
  :: Build an awk source
  set awksrc="%temp%\tmp$$$.awk"
  >  %awksrc% echo BEGIN{
  >> %awksrc% echo number=%1
  >> %awksrc% echo base=2
  >> %awksrc% echo digit="0123456789ABCDEF"
  >> %awksrc% echo result=""
  >> %awksrc% echo while(number!=0)
  >> %awksrc% echo  {
  >> %awksrc% echo   i=number-base*int(number/base)
  >> %awksrc% echo   result=substr(digit,i+1,1)result
  >> %awksrc% echo   number=int(number/base)
  >> %awksrc% echo  }
  >> %awksrc% echo printf"@set bin_=%%s\n",result
  >> %awksrc% echo }
  ::
  :: Run the awk source and the created command script
  set myscript="%temp%\tmp$$$.cmd"
  gawk -f %awksrc%>%myscript%
  call %myscript%
  ::
  :: Clean up
  for %%f in (%awksrc% %myscript%) do if exist %%f del %%f
  ::
  :: Display the results
  echo %1 DEC = %bin_% BIN
  endlocal & goto :EOF
An example of the output
  C:\_D\TEST>cmdfaq 12
  12 DEC = 1100 BIN

A VBScript-aided solution for the Decimal to Binary conversion is
given below
  @echo off & setlocal enableextensions
  rem DEC to BIN
  ::
  :: Usage
  if "%~1"=="" (
    echo.
    echo Usage: %~f0 [DecimalNumber] to be converted to Binary
    goto :EOF)
  ::
  :: Build a Visual Basic Script and run it with Microsoft Windows Script Host
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  cscript //nologo "%temp%\tmp$$$.vbs" %1 > "%temp%\tmp$$$.cmd"
  ::
  :: Utilize the output and display the result
  call "%temp%\tmp$$$.cmd"
  echo Decimal %1 in Binary = %bin_%
  ::
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  number=WScript.Arguments.Unnamed(0)    'VBS
  base=2                                 'VBS
  digit="0123456789ABCDEF"               'VBS
  result=""                              'VBS
  While number <> 0                      'VBS
    i = number - base * Int(number/base) 'VBS
    result = Mid(digit,i+1,1) & result   'VBS
    number = Int(number/base)            'VBS
  Wend                                   'VBS
  WScript.Echo "@set bin_=" & result     'VBS
An example of the output
  C:\_D\TEST>cmdfaq 12
  Decimal 12 in Binary = 1100

Since VBScript has a Hex function, for the Decimal to Hexadecimal
the while loop and the three lines above it can simply be replaced
with
  result = Hex(number)                   'VBS
The same goes for octal.

To conclude the item one more VBScript-aided solution version:
  @echo off & setlocal enableextensions
  rem HEX to DEC
  ::
  :: Usage
  if "%~1"=="" (
    echo.
    echo Usage: %~f0 [HexNumber] to be converted to Decimal
    goto :EOF)
  ::
  :: Build a Visual Basic Script and run it with Microsoft Windows Script Host
  findstr "'%skip%VBS" "%~f0" > "%temp%\tmp$$$.vbs"
  cscript //nologo "%temp%\tmp$$$.vbs" %1 > "%temp%\tmp$$$.cmd"
  ::
  :: Utilize the output and display the result
  call "%temp%\tmp$$$.cmd"
  echo Hexadecimal %1 in Decimal = %dec_%
  ::
  :: Clean up
  for %%f in ("%temp%\tmp$$$.vbs" "%temp%\tmp$$$.cmd") do if exist %%f del %%f
  endlocal & goto :EOF
  '
  number=WScript.Arguments.Unnamed(0)                    'VBS
  k = 1                                                  'VBS
  d = 0                                                  'VBS
  base = 16                                              'VBS
  number=UCase(number)                                   'VBS
  i = Len(number) + 1                                    'VBS
  While i > 1                                            'VBS
    i = i - 1                                            'VBS
    j = Instr (1, "123456789ABCDEF", Mid(number,i,1), 0) 'VBS
    d = d + (j * k)                                      'VBS
    k = base * k                                         'VBS
  Wend                                                   'VBS
  WScript.Echo "@set dec_=" & d                          'VBS
An example of the output
  C:\_D\TEST>cmdfaq 1a
  Hexadecimal 1a in Decimal = 26
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:29 2008
Subject: 89) All of a sudden "echo." doesn't work any more. What's wrong?
Date: Thu,  6 Mar 2008 01:01:29
From: ts@uwasa.fi (Timo Salmi)

Echo is an internal command. One probable cause is that for some
reason you have accidentally created a file with that same name into
the current directory. Consider this demonstration
  @echo off & setlocal enableextensions
  echo whatever>echo
  echo An error will occur:
  echo.
  del echo
  echo No more the error
  echo.
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  An error will occur:
  'echo.' is not recognized as an internal or external command,
  operable program or batch file.
  No more the error

For another catch see item 82) Why does echo 9>temp.txt fail while
echo 10>temp.txt works?
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:30 2008
Subject: 90) How do I get the most recent file within a directory structure?
Date: Thu,  6 Mar 2008 01:01:30
From: ts@uwasa.fi (Timo Salmi)

Pinpointing the most recent file in a folder is not difficult
  @echo off & setlocal enableextensions
  for /f "delims=" %%f in (
   'dir /o:d /a:-d /b c:\YourFolder\*.*') do set latest_="%%~ff"
  echo rem DoWhatever %latest_%
  endlocal & goto :EOF

Getting the most recent file in an entire directory structure is
more complicated:
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Ensure that the auxiliary directory file does not alreaady exist
  for /f "tokens=*" %%f in ("%temp%") do set temp_=%%~sf
  if exist %temp_%temp.dir del %temp_%temp.dir
  ::
  :: Make a directory with the date/time as YYYYMMDD HH:MM
  :: Assumes a DD.MM.YYYY date and a 24 hour time, i.e. no am/pm
  for /f "tokens=*" %%f in ('dir C:\WHATEVER\ /s /b /-c /a:-d-s-h /o:d') do (
   set fdate_=%%~tf
   set fRevisedDate_=!fdate_:~6,4!!fdate_:~3,2!!fdate_:~0,2!
   set ftime_=!fdate_:~11,2!!fdate_:~14,2!
   echo !fRevisedDate_! !ftime_! %%f>>%temp_%temp.dir)
  ::
  :: Sort the directory listing by the date/time stamp
  sort %temp_%temp.dir /o %temp_%tempsort.dir
  ::
  :: Get the last line of the sorted directory listing
  for /f "delims=" %%r in ('type %temp_%tempsort.dir') do set LastLine_=%%r
  echo.%LastLine_%
  ::
  :: Clean up
  for %%f in (temp.dir tempsort.dir) do if exist %temp_%%%f del %temp_%%%f
  endlocal & goto :EOF

The output could be e.g.
  C:\_D\TEST>cmdfaq
  20050414 1742 C:\_F\VPP\DAT\TSKP6504.WKT

If you want only the filename, substitute
  echo %LastLine_:~14%

How about getting the last five most recent files instead of the
latest only? One option is
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Ensure that the auxiliary directory file does not already exist
  for /f "tokens=*" %%f in ("%temp%") do set temp_=%%~sf
  if exist %temp_%temp.dir del %temp_%temp.dir
  ::
  :: Make a directory with the date/time as YYYYMMDD HH:MM
  :: Assumes a DD.MM.YYYY date and a 24 time, i.e. no am/pm
  for /f "tokens=*" %%f in ('dir C:\WHATEVER\ /s /b /-c /a:-d-s-h /o:d') do (
   set fdate_=%%~tf
   set fRevisedDate_=!fdate_:~6,4!!fdate_:~3,2!!fdate_:~0,2!
   set ftime_=!fdate_:~11,2!!fdate_:~14,2!
   echo !fRevisedDate_! !ftime_! %%f>>%temp_%temp.dir)
  ::
  :: Sort the directory listing by the date/time stamp
  sort /r %temp_%temp.dir /o %temp_%tempsort.dir
  if exist %temp_%temp.dir del %temp_%temp.dir
  ::
  :: Get the first five lines of the sorted directory listing
  for /f "delims=" %%r in ('type %temp_%tempsort.dir') do (
   set lineText=%%r
   set /a lineCount+=1
   if !lineCount! LEQ ^5 echo !lineText!>>%temp_%temp.dir)
  sort %temp_%temp.dir
  ::
  :: Clean up
  for %%f in (temp.dir tempsort.dir) do if exist %temp_%%%f del %temp_%%%f
  endlocal & goto :EOF

The output could be e.g.
  C:\_D\TEST>cmdfaq
  20050414 2237 C:\_D\BAS\KOE 2.CMD
  20050415 1205 C:\_D\OPETUS\JATKO\JATKOP.XLS
  20050415 2002 C:\_D\WORD\TIMOSUOM.DIC
  20050415 2120 C:\_D\OPETUS\JOTT\TUL\JOTTTUL.MAI
  20050415 2351 C:\_D\TEST\CMDFAQ.CMD

Another approach to the task at hand would be to customize
 RECENT.CMD CMD shell for RECENT.VBS
 RECENT.VBS Search folders for recent files
They are included as separate files in this CMD FAQ package. The
advantage of the VBS solution is that the date/time stamps will
cover also seconds.

References/Comments:
 http://www.google.com/groups?selm=xFXgtLApDsXCFwsF%40merlyn.demon.co.uk
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:31 2008
Subject: 91) How do I get command-line reference help?
Date: Thu,  6 Mar 2008 01:01:31
From: ts@uwasa.fi (Timo Salmi)

Besides the obvious
 HELP
or for individual commands e.g.
 HELP /?
one can invoke the desktop version
 hh %SYSTEMROOT%\Help\ntcmds.chm

For a single command one can use e.g. the following alternatives
 FOR /?
 HELP FINDSTR | MORE
 hh ntcmds.chm::/set.htm

For putting all the help into continuous text file use
  @echo off & setlocal enableextensions
  if exist help.txt del /p help.txt
  for /f %%f in ('help') do (
   help %%f >> help.txt
   echo ------------------------------------------------------------------------>>help.txt
   echo.>>help.txt
   )
  endlocal & goto :EOF

If you need install Microsoft Windows Script 5.6 for Windows 2000
and XP including Visual Basic Script Edition (VBScript.) you can
look "Script56.CHM" up at Google or start from
 http://www.microsoft.com/downloads/
and then take up the search for "Microsoft Windows Script 5.6". When
you have it installed, the compiled HTML Help file can be called
e.g. with something like
hh "C:\Program Files\Microsoft Windows Script\ScriptDocs\Script56.CHM"

A tip from Walter Briscoe:
"hh -decompile . %SYSTEMROOT%\Help\ntcmds.chm" writes a huge amount
of .htm files in the current directory.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:32 2008
Subject: 92) How do I play a sound from the command line?
Date: Thu,  6 Mar 2008 01:01:32
From: ts@uwasa.fi (Timo Salmi)

The simplest way to emit a brief beep is
 @echo <Ctrl-G>
How to enter the ASCII 7 character depends on your editor program.

If you can get hold of QBASIC it has a PLAY statement. For example
  @echo off & setlocal enableextensions
  set bas_=%temp%\tmp$$$.bas
  for /f "tokens=*" %%f in ("%bas_%") do set bas_=%%~sf
  > %bas_% echo PLAY "l8 o3 cdefgab o4 cd"
  >>%bas_% echo SYSTEM
  qbasic /run %bas_%
  for %%f in (%bas_%) do if exist %%f del %%f
  endlocal & goto :EOF

The Sound Recorder can be used to play a Wave Audio Sound file
(.WAV). For example
 sndrec32.exe /play /close %SYSTEMROOT%\Media\tada.wav
or, without displaying the Sound Recorder window on the desktop
 start /min "" sndrec32 /play /close %SYSTEMROOT%\Media\tada.wav

References/Comments:
 http://support.microsoft.com/kb/q168789/
 http://www.google.com/groups?selm=uJqTHMN9EHA.1400%40TK2MSFTNGP11.phx.gbl
 http://www.google.com/groups?selm=426a617e.3383905%40news.comporium.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:33 2008
Subject: 93) How do I check if my script was given a parameter?
Date: Thu,  6 Mar 2008 01:01:33
From: ts@uwasa.fi (Timo Salmi)

Back to the very basics, with some additions. Below is an example
with three different options, demonstrating an important pitfall
("") and a useful feature (~) on the side

  @echo off & setlocal enableextensions
  ::
  if not [%1]==[] echo %1
  if not [%1]==[] echo %~1
  ::
  set par1=%1
  if defined par1 echo %1
  ::
  if not "%1"=="" echo %1
  ::
  endlocal & goto :EOF

Example output
  C:\_D\TEST>cmdfaq "a b"
  "a b"
  a b
  "a b"
  b""=="" was unexpected at this time.

References/Comments:
 http://www.google.com/groups?selm=43275252%240%2497135%24ed2619ec%40ptn-nntp-reader03.plus.net
 http://www.google.com/groups?selm=443e85ec%240%247489%249b536df3%40news.fv.fi
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:34 2008
Subject: 94) Can I send the script's output both to the screen and a log file?
Date: Thu,  6 Mar 2008 01:01:34
From: ts@uwasa.fi (Timo Salmi)

One option is to use the UNIX-like tee.exe from
 3365706 Apr 15 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUtils.zip
 UnxUtils.zip GNU utilities for native Win32

To show an example apply that on the CMDFAQ.CMD script containing
  @echo off & setlocal enableextensions
  if not [%1]==[] echo %1
  if not [%1]==[] echo %~1
  if not "%1"=="" echo %1
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq "a b" | tee MyLog.txt
  "a b"
  a b
  b""=="" was unexpected at this time.

  C:\_D\TEST>type MyLog.txt
  "a b"
  a b
The error message goes to stdout only.

Another option is to use a screen capture program.

A third one is to write a VBS cscript to do the "tee". Consider the
following example script
  @echo off & setlocal enableextensions
  rem MYTEST.CMD
  echo Test row 1
  echo Test row 2
  endlocal & goto :EOF

Make the following TEE.VBS file
  Dim str
  Do While Not WScript.StdIn.AtEndOfStream
    str = WScript.StdIn.ReadLine
    WScript.StdOut.WriteLine str
    WScript.StdErr.WriteLine str
  Loop

Then on the command line call
  MYTEST | cscript /nologo TEE.VBS > MYLOG.TXT

Also gawk could be used. For example call the following script
  @echo off & setlocal enableextensions
  echo Test row 1
  echo Test row 2
  endlocal & goto :EOF
from the command line using
  CMDFAQ|gawk "{print; print>\"c:\\_m\\out.txt\"}"
The output will be
  C:\_D\TEST>C:\_D\BAS\CMDFAQ.CMD|gawk "{print; print>\"c:\\_m\\out.txt\"}"
  Test row 1
  Test row 2
and the file c:\_m\out.txt whill also contain
  Test row 1
  Test row 2

References/Comments:
 http://www.google.com/groups?selm=42748127%240%24558%24ed2e19e4%40ptn-nntp-reader04.plus.net
 http://www.google.com/groups?selm=1152391556.019753.306150%40m79g2000cwm.googlegroups.com
 http://www.google.com/groups?selm=12avdq4emlftb85%40corp.supernews.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:35 2008
Subject: 95) How to perform an operation on all the filenames listed in a file?
Date: Thu,  6 Mar 2008 01:01:35
From: ts@uwasa.fi (Timo Salmi)

Slightly different variants of this Frequently Asked Question have
been answered many times over. But let's look at this rendition.
Assume that you have in MyList.txt e.g. the following information.
The information could be there for example as a result of a search
with the DIR command.

  C:\Documents and Settings\ts\Local Settings\Temp\GLB62.tmp
  C:\Documents and Settings\ts\Local Settings\Temp\~DF3A.tmp
  C:\WINDOWS\SET3.tmp
  C:\WINDOWS\system32\CONFIG.TMP
  C:\WINDOWS\Temp\scs17.tmp
  C:\_L\TIMO\EXTENS01\EXTEN01.TMP

The script to build MyTask.cmd which you can then call separately.
  @echo off & setlocal enableextensions
  for %%f in (MyTask.cmd) do if exist %%f del %%f
  ::
  :: The command you want to perform on each row.
  :: The "rem" has been inserted for safety
  set todo_=rem del /p
  ::
  :: Delete any old remnants
  for %%f in (MyTask.cmd) do if exist %%f del %%f
  ::
  :: Add the todo_ command at the beginning of each line
  :: Put use quotes in case the source file contains long file names
  for /f "delims=" %%r in ('type MyList.txt') do (
    echo %todo_% "%%~r" >> MyTask.cmd)
  ::
  :: Display the outcome also on the screen
  type MyTask.cmd
  echo.
  dir MyTask.cmd|find /i "MyTask.cmd"
  echo Is ready to be run
  ::
  :: Clean up
  for %%f in (MyTask.cmd) do if exist %%f del %%f
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  rem del /p "C:\Documents and Settings\ts\Local Settings\Temp\GLB62.tmp"
  rem del /p "C:\Documents and Settings\ts\Local Settings\Temp\~DF3A.tmp"
  rem del /p "C:\WINDOWS\SET3.tmp"
  rem del /p "C:\WINDOWS\system32\CONFIG.TMP"
  rem del /p "C:\WINDOWS\Temp\scs17.tmp"
  rem del /p "C:\_L\TIMO\EXTENS01\EXTEN01.TMP"

  03.05.2005  12:35               317 MyTask.cmd
  Is ready to be run

What about making the MyList.txt list. The origin could be anything,
but below is a familiar example how to list all today's *.TMP files
into it.
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Get today's date elements, locale dependent
  set dd_=%date:~0,2%
  set mm_=%date:~3,2%
  set yyyy_=%date:~6,4%
  ::
  :: List all *.TMP file made today
  for /f "delims=" %%f in (
    'dir C:\*.tmp /s /b /-c /a:-d-s-h') do (
      set fdate_=%%~tf
      set fdd_=!fdate_:~0,2!
      set fmm_=!fdate_:~3,2!
      set fyyyy_=!fdate_:~6,4!
      if !fyyyy_!!fmm_!!fdd_! EQU %yyyy_%%mm_%%dd_% (
        echo "%%~f" >> MyList.txt)
    )
  ::
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:36 2008
Subject: 96) Can one use a script to columnize a comma separated values file?
Date: Thu,  6 Mar 2008 01:01:36
From: ts@uwasa.fi (Timo Salmi)

Yes, as shown below
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make a test Comma Separated Value file
  echo a,b,c,de> MyFile.csv
  echo a2,b2,c2,de2>> MyFile.csv
  echo 3,b b3,c234567890,de3>> MyFile.csv
  ::
  :: Columnize
  for /f "tokens=1-4 delims=," %%a in ('type Myfile.csv') do (
   set p1=%%a         .
   set p2=%%b         .
   set p3=%%c         .
   set p4=%%d         .
   echo !p1:~0,9! !p2:~0,9! !p3:~0,9! !p4:~0,9!
   )
  ::
  :: Delete the test file
  for %%f in (MyFile.csv) do if exist %%f del %%f
  endlocal & goto :EOF

The Comma Separated Value file contains
  a,b,c,de
  a2,b2,c2,de2
  3,b b3,c234567890,de3

The test output will be
  C:\_D\TEST>cmdfaq
  a         b         c         de
  a2        b2        c2        de2
  3         b b3      c23456789 de3

The method makes it easy to rearrange the columns, if need be. One
only has to change the order of the fields on the echo line. This
may come handy, in both the directions, in e.g. presenting address
books in different formats. The column format is much easier for a
human to read than csv-formatted address information.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:37 2008
Subject: 97) I need to remove duplicate entries from the output or a file.
Date: Thu,  6 Mar 2008 01:01:37
From: ts@uwasa.fi (Timo Salmi)

Translating Eric Pement's solutions from his UNIX-flavored SED
collection, his option is

  sed "$!N; /^\(.*\)\n\1$/!P; D" MyFile.txt

If one uses third party utilities, and is prepared to go beyond
awk/sed then a uniq.exe UNIX port is one option. Available e.g from
 878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip
 UnxUpdates.zip Updates for UnxUtils GNU utilities for native Win32

A Visual Basic Script (VBScript) aided solution demonstration as the
third option:
  @echo off & setlocal enableextensions
  ::
  :: Make a test file
  for %%i in (1 2 2 2) do echo This is line %%i>>MyFile.txt
  echo.>>MyFile.txt
  for %%i in (6 6 8) do echo This is line %%i>>MyFile.txt
  ::
  :: Build a Visual Basic Script
  set skip=
  set vbs_=%temp%\tmp$$$.vbs
  findstr "'%skip%VBS" "%~f0" > "%vbs_%"
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%vbs_%" < MyFile.txt
  ::
  :: Clean up
  for %%f in ("%vbs_%" MyFile.txt) do del %%f
  endlocal & goto :EOF
  '
  '.............................................
  'The Visual Basic Script
  '
  prev = ""                                 'VBS
  first = true                              'VBS
  Do While Not WScript.StdIn.AtEndOfStream  'VBS
    str = WScript.StdIn.ReadLine            'VBS
    If (str <> prev) or first Then          'VBS
      WScript.StdOut.WriteLine str          'VBS
    End If                                  'VBS
    prev = str                              'VBS
    first = false                           'VBS
  Loop                                      'VBS

The input file is
  This is line 1
  This is line 2
  This is line 2
  This is line 2

  This is line 6
  This is line 6
  This is line 8

The output will be
  This is line 1
  This is line 2

  This is line 6
  This is line 8

Finally, if(!) you are prepared to accept omitting empty lines, then
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make a test file
  for %%i in (1 2 2 2) do echo This is line %%i>>MyFile.txt
  echo.>>MyFile.txt
  for %%i in (6 6 8) do echo This is line %%i>>MyFile.txt
  ::
  :: Process
  set prev=
  for /f "delims=" %%a in ('type Myfile.txt') do (
    set str=%%a
    if not [!str!]==[!prev!] echo %%a
    set prev=!str!
    )
  ::
  :: Clean up
  for %%f in (MyFile.txt) do del %%f
  endlocal & goto :EOF
The output of the previous example would be
  C:\_D\TEST>cmdfaq
  This is line 1
  This is line 2
  This is line 6
  This is line 8

Can this task be solved with a pure cmd script so that the empty
lines are not omitted? Yes, but the solution is a bit kludgy and
complicated. And the issue of poison characters remains.
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make a test file
  echo.>>MyFile.txt
  for %%i in (2 3 3 3) do echo This  is  line  %%i>>MyFile.txt
  echo.>>MyFile.txt
  for %%i in (7 7 9 10 11) do echo This is line "%%i">>MyFile.txt
  ::
  :: Process
  for %%v in (prev LineCount) do set %%v=
  for /f "delims=" %%a in (
    'findstr /n /v /c:"SomeUnlikelyString" Myfile.txt') do (
      set str=%%a
      set /a LineCount+=1
      set /a mod = LineCount/10 + 2
      call :WriteOneLine "!str!" "!prev!" !mod!
      set prev=!str!
    )
  ::
  :: Clean up
  for %%f in (MyFile.txt) do del %%f
  endlocal & goto :EOF
  ::
  :: =============================================
  :WriteOneLine
  setlocal
  set str=%~1
  set prev=%~2
  set offset=%3
  set str=!str:~%offset%!
  set prev=!prev:~%offset%!
  if not [!str!]==[!prev!] echo.!str!
  endlocal & goto :EOF

The test input file will be
---

This  is  line  2
This  is  line  3
This  is  line  3
This  is  line  3

This is line "7"
This is line "7"
This is line "9"
This is line "10"
This is line "11"
---

The test output will be
---
C:\_D\TEST>cmdfaq

This  is  line  2
This  is  line  3

This is line "7"
This is line "9"
This is line "10"
This is line "11"
---

To put things in perspective. By quite a coincidence I needed the
other day to perform that task myself combining two lists of
newsgroups and then removing the duplicates. I didn't have to think
for one second which route to take when the situation came up for
real. Skipped all the nice and fancy scripts and chose the UNIX port
uniq.exe without any hesitation.

References/Comments:
 http://www.google.com/groups?selm=d59ur0%24182m%241%40agate.berkeley.edu
 http://www.google.com/groups?selm=427aef2c%241_2%40alt.athenanews.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:38 2008
Subject: 98) How do I equate all zip files with the date of their latest file?
Date: Thu,  6 Mar 2008 01:01:38
From: ts@uwasa.fi (Timo Salmi)

A typical archive maintainer's task.
  @echo off
  rem
  rem   Covert a zip file datestamp to equal the datestamp of the
  rem   most recent file within the zip archive. Traverses all the
  rem   zip files in the default folder.
  rem
  rem   Needs zip.exe from
  rem    206026 Mar 12 2005 ftp://garbo.uwasa.fi/win95/arcers/zip231xN.zip
  rem    zip231xN.zip Info-ZIP command-line zip for Win9x/NT/2K/XP/2K3
  rem   or more generally http://garbo.uwasa.fi/win95/arcers.html
  rem
  rem   Uses the switch "-o" to "make zipfile as old as latest entry"
  rem
  rem   By Prof. Timo Salmi
  rem   Last updated Fri 12-Aug-2005
  ::
  set TZ=Europe/Helsinki
  if not exist *.zip goto _nofile
  for %%f in (*.zip) do zip -o %%f
  dir *.zip | find /i ".ZIP"
  goto _out
  ::
  :_nofile
  echo No .zip files found to process
  goto _out
  ::
  :_out
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:39 2008
Subject: 99) How do I "touch" a file to update its last modified datestamp?
Date: Thu,  6 Mar 2008 01:01:39
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  if [%1]==[] (
    echo Usage: %~0 ["FileName"]
    echo Wildcards allowed
    goto :EOF
    )
  for %%f in ("%~1") do copy /b /v %%f +,,> nul
  dir "%~1"
  endlocal & goto :EOF

Also see item #134.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:40 2008
Subject: 100) How can I identify and copy the five latest files from a folder?
Date: Thu,  6 Mar 2008 01:01:40
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions enabledelayedexpansion
  set count_=0
  for /f "delims=" %%f in (
    'dir /o:-d /a:-d /b c:\MyFolder\*.*') do (
    set file_="%%~ff"
    set /a count_+=1
    if !count_! LEQ 5 echo rem copy !file_!
    )
  endlocal & goto :EOF

Given that solution it is as easy to identify the five oldest
files. Left as an exercise.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:41 2008
Subject: 101) How to capture Volume Serial Number into an environment variable?
Date: Thu,  6 Mar 2008 01:01:41
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  for /f "skip=1 tokens=5" %%s in ('vol c:') do set volc_=%%s
  echo %volc_%
  endlocal & goto :EOF

The output cound be e.g.
  C:\_D\TEST>cmdfaq
  D634-E1B2

Why? Do the "math". Since the output of
  C:\_D\TEST>vol c:
   Volume in drive C is MY_C
   Volume Serial Number is D634-E1B2

Likewise, you can fairly easily get the label of a volume:
  @echo off & setlocal enableextensions
  set target_=C:\
  for /f "tokens=6" %%f  in (
    'dir %target_%^|find "Volume in drive "') do (
    set label_=%%f)
  echo The label of Volume %target_% is %label_%
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:42 2008
Subject: 102) How can I extract the individual bits from a decimal byte?
Date: Thu,  6 Mar 2008 01:01:42
From: ts@uwasa.fi (Timo Salmi)

   Basically this is the same task as the decimal to binary
conversion in item #32. The formulation below emphasizes extracting
each bit of a decimal byte individually. A byte contains 8 bits,
usually labeled from 0 to 7. It also shows that are many different
options to perform a task since the solution here differs
considerably from the one used in item #32.
   These bitwise operations were the key elements of programming
back in the days of Vic 20 and Commodore 64, but can still arise in
the present day as seen in the references.

  @echo off & setlocal enableextensions enabledelayedexpansion
  set decimal_=%1
  set /a b0=%decimal_% ^& 1
  set /a b1=%decimal_% ^& 2
  set /a b2=%decimal_% ^& 4
  set /a b3=%decimal_% ^& 8
  set /a b4=%decimal_% ^& 16
  set /a b5=%decimal_% ^& 32
  set /a b6=%decimal_% ^& 64
  set /a b7=%decimal_% ^& 128
  set i=-1
  for %%b in (!b0! !b1! !b2! !b3! !b4! !b5! !b6! !b7!) do (
    set bit=%%b
    set /a i+=1
    if !bit! EQU 0 (echo bit !i! = 0) else (echo bit !i! = 1)
  )
  endlocal & goto :EOF
An example of the output
  C:\_D\TEST>cmdfaq 12
  bit 0 = 0
  bit 1 = 0
  bit 2 = 1
  bit 3 = 1
  bit 4 = 0
  bit 5 = 0
  bit 6 = 0
  bit 7 = 0

Examples of bitwise operations
  @echo off & setlocal enableextensions
  set dec1_=121
  set dec2_=145
  ::
  set /a decand_=%dec1_% ^& %dec2_%
  echo %dec1_% AND %dec2_% = %decand_%
  ::
  set /a decor_=%dec1_% ^| %dec2_%
  echo %dec1_% OR  %dec2_% = %decor_%
  ::
  set /a decxor_=%dec1_% ^^ %dec2_%
  echo %dec1_% XOR %dec2_% = %decxor_%
  ::
  set /a decnot_=%dec1_% ^^ 255
  echo NOT %dec1_% = %decnot_%
  ::
  set dec3_=1
  set shft_=3
  set decshl_=%dec3_%
  set /a decshl_ ^<^<= %shft_%
  echo %dec3_% SHL %shft_% = %decshl_%
  ::
  set dec4_=128
  set shft_=1
  set decshr_=%dec4_%
  set /a decshr_ ^>^>= %shft_%
  echo %dec4_% SHR %shft_% = %decshr_%
  ::
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  121 AND 145 = 17
  121 OR  145 = 249
  121 XOR 145 = 232
  NOT 121 = 134
  1 SHL 3 = 8
  128 SHR 1 = 64
The SHL (shift left) can be used to get the powers of 2.

References/Comments:
 http://www.google.com/groups?selm=4285a523%240%2493767%24ed2619ec%40ptn-nntp-reader01.plus.net
 http://www.google.com/groups?selm=nfbd81pp3ebfjjdoqhovujsvbj1q5efn49%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:43 2008
Subject: 103) How do I exit a loop by pressing a key?
Date: Thu,  6 Mar 2008 01:01:43
From: ts@uwasa.fi (Timo Salmi)

You may wish to revisit item #14 first. Anyway:
  @echo off & setlocal enableextensions
  ::
  :: Test for CHOOSE.EXE availability at path / in the current folder
  for %%f in ("CHOOSE.EXE") do set found_=%%~$PATH:f
  if exist CHOOSE.EXE set found_=CHOOSE.EXE
  if "%found_%"=="" (
    echo CHOOSE.EXE choice.com clone not found.
    echo Available from ftp://garbo.uwasa.fi/pc/link/tscmd.zip
    goto :EOF)
  ::
  echo Press x to exit the loop
  ::
  :_loop
  set /a i_+=1
  choose /n /c:nx /tn,0 > nul
  if %errorlevel% NEQ 2 goto _loop
  ::
  echo i_=%i_%
  endlocal & goto :EOF

The output would be e.g.
  C:\_D\TEST>cmdfaq
  Press x to exit the loop
  i_=37
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:44 2008
Subject: 104) How can one remove double quotes from a script variable?
Date: Thu,  6 Mar 2008 01:01:44
From: ts@uwasa.fi (Timo Salmi)

There are different methods. First
  @echo off & setlocal enableextensions
  set var="a b c d"
  echo %var%
  set var=%var:"=%
  echo %var%
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  "a b c d"
  a b c d
Note that ALL the quotes are removed. Also those potentially within
the string.

The other methods include
  @echo off & setlocal enableextensions
  ::
  set var="a b c d"
  echo %var%
  for %%f in (%var%) do echo %%~f
  ::
  set var="cmdfaq.*"
  echo %var%
  for %%f in (%var%) do echo %%~f
  ::
  set var=%var:"=%
  echo %var%
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  "a b c d"
  a b c d
  "cmdfaq.*"
  CMDFAQ.CMD
  cmdfaq.*

Note how the asterisk * is expanded for an existing file name. In
fact, as seen in many examples, if you had
  @echo off & setlocal enableextensions
  set var="cmdfaq*.*"
  echo %var%
  for %%f in (%var%) do echo %%~ff
  endlocal & goto :EOF
the output would be something like
  C:\_D\TEST>cmdfaq
  "cmdfaq*.*"
  C:\_D\TEST\CMDFAQ THIRD.CMD
  C:\_D\TEST\CMDFAQ.CMD
  C:\_D\TEST\CMDFAQ2.CMD

Although not practical, for demonstration one can also have
  @echo off & setlocal enableextensions
  set var="a b c d"
  echo %var%
  for /f "tokens=*" %%f in ("%temp%") do set temp_=%%~sf
  echo @set var=%var%|sed -e "s/\"//g">%temp_%\tmp.cmd
  for %%c in (call del) do %%c %temp_%\tmp.cmd
  echo %var%
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  "a b c d"
  a b c d
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:45 2008
Subject: 105) How to detect whether or not a folder contains hidden files?
Date: Thu,  6 Mar 2008 01:01:45
From: ts@uwasa.fi (Timo Salmi)

As a sideline, note the usage of the caret ^ for dividing a command
structure over several lines to avoid wrapping problems in
presenting a solution.
  @echo off & setlocal enableextensions
  dir C:\MyFolder\*.* /b /a:h^
   |find /v "SomeUnlikelyString">nul^
   && set hidden_=true^
   ||set hidden_=false
  echo hidden_=%hidden_%
  endlocal & goto :EOF

The output will be either
  C:\_D\TEST>cmdfaq
  hidden_=true
or
  C:\_D\TEST>cmdfaq
  File Not Found
  hidden_=false

If you want to get rid of the "File Not Found" use the alternatives
(posted by William Allen)
  @echo off & setlocal enableextensions
  dir C:\MyFolder\*.* /a:h>nul 2>&1
  if errorlevel 1 (set hidden_=false) else (set hidden_=true)
  echo hidden_=%hidden_%
  endlocal & goto :EOF
or
  @echo off & setlocal enableextensions
  dir C:\_M\TEMP\*.* /a:h>nul 2>&1
  set hidden_=true& dir C:\MyFolder\*.* /a:h>nul 2>&1||set hidden_=false
  echo hidden_=%hidden_%
  endlocal & goto :EOF

Another option is
  @echo off & setlocal enableextensions
  attrib c:\_m\temp\*.*|findstr /b "....H">nul
  if errorlevel 1 (set hidden_=false) else (set hidden_=true)
  echo hidden_=%hidden_%
  endlocal & goto :EOF

Note how the method above can also be used e.g. for testing if a
file is read-only:
  @echo off & setlocal enableextensions
  if [%1]==[] (
    echo Usage: %~f0 [FileName]
    goto :EOF
  )
  if not exist "%~1" (
    echo File "%~1" not found
    goto :EOF
  )
  attrib "%~1"|findstr /b ".....R">nul
  if errorlevel 1 (set readonly_=false) else (set readonly_=true)
  echo File "%~1" read-only status: %readonly_%
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:46 2008
Subject: 106) How to test whether a variable is a non-negative integer?
Date: Thu,  6 Mar 2008 01:01:46
From: ts@uwasa.fi (Timo Salmi)

This is one of the items which arose from a solution I needed
myself. Test for a decimal (10-base) non-negative integer. The
original solution is given after the simpler one below:
  @echo off & setlocal enableextensions
  if "%~1"=="" (
    echo Usage: %~f0 Parameter
    goto :EOF)
  ::
  :: Get the parameter into a variable
  set s=%~1
  ::
  :: Do a regular expression (/r) findstr complement
  echo %s%|findstr /r "[^0-9]">nul
  if %errorlevel% GTR 0 (set isInteger=true) else (set isInteger=false)
  ::
  :: Show the result
  echo %s%
  echo isInteger=%isInteger%
  ::
  endlocal & goto :EOF
Examples of output
  C:\_D\TEST>cmdfaq 1234
  1234
  isInteger=true
or
  C:\_D\TEST>cmdfaq FF
  FF
  isInteger=false

Actually, a non-negative integer!

More fully
  @echo off & setlocal enableextensions
  if "%~1"=="" (
    echo Usage: %~f0 Parameter
    goto :EOF)
  ::
  :: Get the parameter into a variable
  set s=%~1
  ::
  :: Do a regular expression (/r) findstr complement and avoid the octal trap
  echo %s%|findstr /r "[^0-9]">nul||set isDecInteger=true
  if defined isDecInteger if not "%s:~1,2%"=="" if "%s:~0,1%"=="0" set IsDecInteger=
  ::
  :: Show the result
  if defined IsDecInteger (
    echo %s% is a regular, non-negative integer
    ) else (
    echo %s% is not a regular, non-negative integer
    )
  ::
  endlocal & goto :EOF

Originaly, I had
  @echo off & setlocal enableextensions enabledelayedexpansion
  if "%~1"=="" (
    echo Usage: %~f0 Parameter
    goto :EOF)
  ::
  :: Get the parameter into a variable
  set s=%~1
  ::
  :: Get its length, counting from zero
  set charCount=0
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if defined si set /a charCount+=1)
  set /a charCount=%charCount%-1
  ::
  :: Test that only valid characters are present
  set isInteger=true
  for /l %%c in (0,1,%charCount%) do (
    set si=!s:~%%c,1!
    echo 1234567890|findstr /l "!si!">nul
    if !errorlevel! GTR 0 set isInteger=false
    )
  ::
  :: Show the result
  echo %s%
  echo isInteger=%isInteger%
  ::
  endlocal & goto :EOF
Examples of output
  C:\_D\TEST>cmdfaq 1234
  1234
  isInteger=true
or
  C:\_D\TEST>cmdfaq FF
  FF
  isInteger=false

The solution can be expanded to other numeric or alphabetic validity
tests. For example to test if a variable is a positive decimal
number.
  @echo off & setlocal enableextensions enabledelayedexpansion
  if "%~1"=="" (
    echo Usage: %~f0 Parameter
    goto :EOF)
  ::
  :: Get the parameter into a variable
  set s=%~1
  ::
  :: Get its length, counting from zero
  set charCount=0
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if defined si set /a charCount+=1)
  set /a charCount=%charCount%-1
  ::
  :: Test that only valid characters are present
  set isNumeric=true
  set pointCount=0
  for /l %%c in (0,1,%charCount%) do (
    set si=!s:~%%c,1!
    echo 1234567890.|findstr /l "!si!">nul
    if !errorlevel! GTR 0 set isNumeric=false
    if [!si!]==[.] set /a pointCount+=1
    )
  if %pointCount% GTR 1 set isNumeric=false
  ::
  :: Show the result
  echo %s%
  echo isNumeric=%isNumeric%
  ::
  endlocal & goto :EOF
The output could be e.g.
  C:\_D\TEST>cmdfaq 12.34
  12.34
  isNumeric=true
or
  C:\_D\TEST>cmdfaq 1..
  1..
  isNumeric=false

Or, more concisely
  @echo off & setlocal enableextensions enabledelayedexpansion
  if "%~1"=="" (
    echo Usage: %~f0 Parameter
    goto :EOF)
  ::
  :: Get the parameter into a variable
  set s=%~1
  ::
  :: Test if non-valid characters are present
  set isNumeric=true
  echo %s%|findstr "[^0-9.]">nul
  if %errorlevel% EQU 0 set isNumeric=false
  ::
  :: Count the decimal points in the variable s
  set pointCount=0
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if [!si!]==[.] set /a pointCount+=1
    )
  if %pointCount% GTR 1 set isNumeric=false
  ::
  :: Show the result
  echo %s%
  echo isNumeric=%isNumeric%
  ::
  endlocal & goto :EOF

Another example. The parameter to be given is a time parameter in
the HH:MM format. Test for its validity.
  @echo off & setlocal enableextensions enabledelayedexpansion
  if "%~1"=="" (
    echo Usage: %~f0 TimeParameterHH:MM
    goto :EOF)
  ::
  :: Test for the time parameter validity
  :: Get the parameter into a variable
  set s=%~1

  :: Get its length and count the number of colons
  set charCount=0
  set pointCount=0
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if defined si set /a charCount+=1
    if [!si!]==[:] set /a pointCount+=1
    )

  :: Test that only valid characters are present
  set isNumeric=true
  echo %s%|findstr "[^0-9:]">nul
  if %errorlevel% EQU 0 set isNumeric=false
  ::
  :: Test for the right composition
  if %pointCount% GTR 1 set isNumeric=false
  if %charCount% GTR 5 set isNumeric=false
  ::
  :: Get the components
  for /f "tokens=1,2 delims=:" %%a in ("%s%") do (
  set shour=%%a
  set sminute=%%b)
  if not defined sminute set sminute=0
  ::
  :: Test that the time is within bounds
  if %shour% GTR 23 set isNumeric=false
  if %sminute% GTR 59 set isNumeric=false
  ::
  :: Show the result
  echo s=%s%
  echo shour=%shour%
  echo sminute=%sminute%
  echo isNumeric=%isNumeric%
  ::
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=d97av3%24mrv%241%40agate.berkeley.edu
 http://www.jsifaq.com/SF/Tips/Tip.aspx?id=9692
 http://www.google.com/groups?selm=1168700139.287904.190160%4051g2000cwl.googlegroups.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:47 2008
Subject: 107) How to do non-trivial renaming such as IMG*.jpg to IMG_*.jpg?
Date: Thu,  6 Mar 2008 01:01:47
From: ts@uwasa.fi (Timo Salmi)

Consider the following situation
  Rename IMG1225.jpg to IMG_1225.jpg
  Rename IMG1226.jpg to IMG_1226.jpg
  Rename IMG1227.jpg to IMG_1227.jpg
  Rename IMG1228.jpg to IMG_1228.jpg

First off this can't be solved as
  ren C:\WHATEVER\IMG*.jpg IMG_*.*
since it would give you (dropping the thousands):
  IMG_225.jpg
  IMG_226.jpg
  IMG_227.jpg
  IMG_228.jpg

If you try
  @echo off & setlocal enableextensions enabledelayedexpansion
  for %%f in (C:\WHATEVER\*.jpg) do (
    rem echo %%~df%%~pf%%~nf%%~xf
    set base=%%~nf
    set base=!base:IMG=IMG_!
    ren %%~df%%~pf%%~nf%%~xf !base!%%~xf
  )
  endlocal & goto :EOF
you'll get
  IMG_1226.jpg
  IMG_1227.jpg
  IMG_1228.jpg
  IMG__1225.jpg

The cmd.exe is a command line interpreter, not a compiler. The
renaming forms a kind of a ring with the first of your files popping
up anew renamed within the execution. The solution is to use a
formulation of FOR which does not have that "bug" or "feature" in
cmd.exe.
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f "delims=" %%f in (
    'dir /a:-d /b /s /o:n C:\WHATEVER\*.jpg') do (
    set base=%%~nf
    set base=!base:IMG=IMG_!
    ren "%%~df%%~pf%%~nf%%~xf" "!base!%%~xf"
  )
  endlocal & goto :EOF
This time you will get
  IMG_1225.jpg
  IMG_1226.jpg
  IMG_1227.jpg
  IMG_1228.jpg

Note that the above solution will recurse to subfolders, as well. If
you do not want that, use
  @echo off & setlocal enableextensions enabledelayedexpansion
  set folder_=C:\WHATEVER
  ::
  for /f "delims=" %%f in (
    'dir /a:-d /b /o:n %folder_%\*.jpg') do (
    set base=%%~nf
    set base=!base:IMG=IMG_!
    ren "%folder_%\%%~nf%%~xf" "!base!%%~xf"
  )
  endlocal & goto :EOF
The dilemma with dir /b without the /s is that %%~df and %%~pf will
not point where one would intuitively expect them to point. Instead
they point to the script's default folder. Thus the above
alternative is needed.

Incidentally, the IMG_1225.JPG format is the naming convention for
digiphotos on a Canon Ixus. It might be used on other cameras as
well, but that I know of.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:48 2008
Subject: 108) How can I execute a script one line at a time to debug it?
Date: Thu,  6 Mar 2008 01:01:48
From: ts@uwasa.fi (Timo Salmi)

Not as efficiently and conveniently than in the MS-DOS command.com
method "command /y /c". However, you can use the following obvious
construct:

  @echo off & setlocal enableextensions
  set debugon=true
  @if defined debugon echo on
  whatever
  @if defined debugon pause
  whatever
  @if defined debugon pause
  whatever
  @if defined debugon pause
  endlocal & goto :EOF

Given that you have an original script file myscript.cmd which you
wish to debug by stepping through it one line at a time, the next
question is how do you easily insert the debug lines without
disturbing the original. Essentially, use the following G(nu)AWK
command on the command line
  gawk "{printf \"%s\n@if defined debugon pause\n\",$0}" myscript.cmd>mydebug.cmd
Before using, you may have "manually" to see to the lines
  set debugon=true
  @if defined debugon echo on

The advantage of the "@if defined debugon pause" is that you can
customize your debugging by inserting such lines only where of
essence. It usually is not necessary to have it on every second
line.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:49 2008
Subject: 109) How do I open e.g. three separate instances of notepad at one go?
Date: Thu,  6 Mar 2008 01:01:49
From: ts@uwasa.fi (Timo Salmi)

> I have a file OPENTEXT.CMD that contains the following lines:
>  notepad textfile1.txt
>  notepad textfile2.txt
>  notepad textfile3.txt
> When I type OPENTEXT, I want all three of the text files to open in
> separate Notepad windows.

START starts a separate window to run a specified program or
command.
  @echo off & setlocal enableextensions
  start "" notepad textfile1.txt
  start "" notepad textfile2.txt
  start "" notepad textfile3.txt
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:50 2008
Subject: 110) Can I use a script to determine if a specific printer exists?
Date: Thu,  6 Mar 2008 01:01:50
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  set find_=HP DeskJet 895Cxi
  net view \\%COMPUTERNAME%^
    |findstr /c:"Print  "^
    |findstr /c:" %find_% ">nul
  if %errorlevel% EQU 0 (
    echo Found %find_%
    ) else (
    echo Did not find %find_%)
  endlocal & goto :EOF
The output would be e.g.
  C:\_D\TEST>cmdfaq
  Found HP DeskJet 895Cxi
For help information try
  hh ntcmds.chm::/net_view.htm
  hh ntcmds.chm::/findstr.htm
The carets (^) in the code are used to divide a long command on
multiple lines.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:51 2008
Subject: 111) How can I detect if a folder is shared or not?
Date: Thu,  6 Mar 2008 01:01:51
From: ts@uwasa.fi (Timo Salmi)

The same method as in the previous item can be used e.g. to check if
a folder is shared or not.
  @echo off & setlocal enableextensions
  set find_=C:\_M
  net share|find /i "%find_% ">nul
  if %errorlevel% EQU 0 (
    echo Folder "%find_%" is shared
    ) else (
    echo Folder "%find_%" is not shared or does not exist)
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:52 2008
Subject: 112) Help, an old program fails to run since I have no floppy drive.
Date: Thu,  6 Mar 2008 01:01:52
From: ts@uwasa.fi (Timo Salmi)

 Q: I am trying trun an old program. But it fails since the program
requires a disk present in the floppy drive A: which I do not have.

 A: This trick sometimes works if the old program just wants to have
a floppy present to write to
  @echo off & setlocal enableextensions
  mkdir C:\_A
  subst A: C:\_A
  TheProgram
  subst /d A:
  rmdir C:\_A
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:53 2008
Subject: 113) How do I find all *.TXT files on the C: drive sorted by size?
Date: Thu,  6 Mar 2008 01:01:53
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions enabledelayedexpansion
  if exist "%temp%\temp.dir" del "%temp%\temp.dir"
  for /f "delims=" %%f in (
    'dir /a:-d /b /s c:\*.txt') do (
    set filename_="%%~ff"
    set filesize_=0000000000%%~zf
    set filesize_=!filesize_:~-10!
    echo !filesize_! !filename_! >>"%temp%\temp.dir"
    )
  sort /r "%temp%\temp.dir"
  if exist "%temp%\temp.dir" del "%temp%\temp.dir"
  endlocal & goto :EOF

The output might start with something like
 0000401272 "c:\INF2\FAQPAS.TXT"
 0000389257 "c:\BAT\1BATFAQ.TXT"
 0000359101 "c:\CHYDE\INDEX.TXT"
 0000272243 "c:\CMD\1CMDFAQ.TXT"

Should one wish to get rid of the leading filesize:
  @echo off & setlocal enableextensions enabledelayedexpansion
  if exist "%temp%\temp.dir" del "%temp%\temp.dir"
  for /f "delims=" %%f in (
    'dir /a:-d /b /s c:\*.txt') do (
    set filename_="%%~ff"
    set filesize_=0000000000%%~zf
    set filesize_=!filesize_:~-10!
    echo !filesize_! !filename_! >>"%temp%\temp.dir"
    )
  ::
  for /f "delims=" %%a in ('sort /r "%temp%\temp.dir"') do (
    set filename_=%%a
    set filename_=!filename_:~11!
    echo !filename_!
    )
  ::
  if exist "%temp%\temp.dir" del "%temp%\temp.dir"
  endlocal & goto :EOF

Then the output would be something like
"c:\_F\INF2\FAQPAS.TXT"
"c:\_F\BAT\1BATFAQ.TXT"
"c:\_F\CHYDE\INDEX.TXT"
"c:\_F\CMD\1CMDFAQ.TXT"
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:54 2008
Subject: 114) How do I pick a file's lines that are three characters long?
Date: Thu,  6 Mar 2008 01:01:54
From: ts@uwasa.fi (Timo Salmi)

> I have a text file with a list of around 900 names in it. I'd like
> to be able to retrieve all the names that are three characters long

The method is an adaptation of items #26 and #27 of this FAQ.
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f "delims=" %%a in ('type myfile.txt') do (
    set name_=%%a
    set charCount=0
    for /l %%c in (0,1,255) do (
      set si=!name_:~%%c,1!
      if defined si set /a charCount+=1)
    if !charCount! EQU 3 echo !name_!
    )
  endlocal & goto :EOF
This method cannot handle names with the "poison characters".

However, a much simpler and still an all-script solution is
  findstr "^...$" myfile.txt

With sed it would be
  sed -n "s/^...$/&/p" myfile.txt

With gawk
  gawk "{if(length()==3)printf\"%%s\n\",$0}" myfile.txt

What if you want all the names that are three or less characters
long?
  findstr "^.$ ^..$ ^...$" myfile.txt
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:55 2008
Subject: 115) How can I decompose the path to be one folder per line?
Date: Thu,  6 Mar 2008 01:01:55
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  echo %path%;^
    |gawk -F; "{for (i=1;i<=NF-1;++i) printf \"%%s\n\",$i}"
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  c:\_f\xtools
  c:\_f\tools
  c:\_f\ftools
  c:\_e\arczip
  C:\WINDOWS\system32
  C:\WINDOWS
  C:\WINDOWS\System32\Wbem
  C:\Program Files\PC-Doctor for Windows\services
  C:\Program Files\TSEpro
  C:\Program Files\010Editor

With SED
  path | sed -e s/.*=// -e s/;/\r\n/g

Or with straight script
  @echo off & setlocal enableextensions
  for /f "tokens=1-15 delims=;" %%a in ("%path%") do (
    if not [%%a]==[] echo %%a
    if not [%%b]==[] echo %%b
    if not [%%c]==[] echo %%c
    if not [%%d]==[] echo %%d
    if not [%%e]==[] echo %%e
    if not [%%f]==[] echo %%f
    if not [%%g]==[] echo %%g
    if not [%%h]==[] echo %%h
    if not [%%i]==[] echo %%i
    if not [%%j]==[] echo %%j
    if not [%%k]==[] echo %%k
    if not [%%l]==[] echo %%l
    if not [%%m]==[] echo %%m
    if not [%%n]==[] echo %%n
    if not [%%o]==[] echo %%o
    )
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=4321fd74%240%2417479%24ed2e19e4%40ptn-nntp-reader04.plus.net
 http://www.google.com/groups?selm=ha54i15ju5b3ek2qhj4c33cd0qplhmhc6u%404ax.com
 http://www.google.com/groups?selm=uatXKdCm5DODFwTL%40merlyn.demon.co.uk
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:56 2008
Subject: 116) How do I get a list all the *.BAT files which are at path?
Date: Thu,  6 Mar 2008 01:01:56
From: ts@uwasa.fi (Timo Salmi)

Expanding on the solution given in the second link in the
"References/Comments:" of the previous item we can e.g. list all the
*.BAT files appearing at the path:
  @echo off & setlocal enableextensions
  for %%a in ("%path:;=" "%") do (
    for /f %%f in ('dir /b /a:-d /o:n "%%~a\*.bat"') do (
      echo %%~a\%%f)
    )>>"%temp%\temp.dir"
  for %%c in (type del) do call %%c "%temp%\temp.dir"
  endlocal & goto :EOF

There is, however an even better solution which avoids the "File not
found" problem for folders that contain no *.BAT files. The snippet
is from the reference at the end of this item.
  @echo off & setlocal enableextensions
  for %%a in ("%path:;=" "%") do (
    for %%g in ("%%~a\*.bat") do echo %%~fg)
  endlocal & goto :EOF

A tangent question of a Unix "which" done with script commands is
covered in item #46.

References/Comments:
 http://www.google.com/groups?selm=m2k4i1luek2th2087u045sasa1n112dhlf%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:57 2008
Subject: 117) Is it possible to get the physical memory from the cmd?
Date: Thu,  6 Mar 2008 01:01:57
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  for /f "tokens=4,5" %%a in (
    'systeminfo^|find "Total Physical Memory"') do (
    set memory_=%%a
    set units_=%%b)
  echo Memory = %memory_% %units_%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  Memory = 511 MB
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:58 2008
Subject: 118) How to handle irregular empty fields of a CSV file?
Date: Thu,  6 Mar 2008 01:01:58
From: ts@uwasa.fi (Timo Salmi)

This comes out of a real-life production script problem I had
myself. The CSV file format is useful for many tasks because of its
relation to Excel. Consider the following, simple example CSV file
myfile.csv

  a11,a12,a13
  a21,,a23

The script
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f "tokens=1-3 delims=," %%a in ('type "myfile.csv"') do (
    set s1_=%%a
    set s2_=%%b
    set s3_=%%c
    if defined s1_ (echo !s1_!) else (echo ..)
    if defined s2_ (echo !s2_!) else (echo ..)
    if defined s3_ (echo !s3_!) else (echo ..)
    )
  endlocal & goto :EOF

will produce
  a11
  a12
  a13
  a21
  a23
  ..

The .. line obviously is mislocated.

Is there a way out? One option is inserting a "-" within the empty ,,
pair before going through the file

  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Make a demonstration test file
  echo a11,a12,a13>mytest.csv
  echo a21,,a23>>mytest.csv
  ::
  :: The actual routine
  for /f "delims=" %%a in ('type "mytest.csv"') do (
    set s_=%%a
    set s_=!s_:,,=,-,!
    set s_=!s_:,,=,-,!
    for /f "tokens=1-3 delims=," %%a in ("!s_!") do (
      set s1_=%%a
      set s2_=%%b
      set s3_=%%c
      if not [!s1_!]==[-] (echo !s1_!) else (echo ..)
      if not [!s2_!]==[-] (echo !s2_!) else (echo ..)
      if not [!s3_!]==[-] (echo !s3_!) else (echo ..)
      )
    )
  ::
  :: Clean up
  for %%f in (mytest.csv) do if exist %%f del %%f
  endlocal & goto :EOF

Now the output is the more logical
  a11
  a12
  a13
  a21
  ..
  a23

There is a subtle catch. Performing the substitution twice in the
script above is not a mistake. It is required since in the more
generic case where can be either an odd or and even number of
adjacent ,, pairs. Ensuring the substitution globally takes two
passes. This is not only script-related. Even any text editor or SED
requires the same.

Also a Visual Basic Script (VBScript) aided solution can be used
  @echo off & setlocal enableextensions
  ::
  :: Make a demonstration test file
  echo a11,a12,a13>mytest.csv
  echo a21,,a23>>mytest.csv
  ::
  :: Build a Visual Basic Script
  set skip=
  set vbs_=%temp%\tmp$$$.vbs
  findstr "'%skip%VBS" "%~f0" > "%vbs_%"
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%vbs_%" < mytest.csv
  ::
  :: Clean up
  for %%f in ("%vbs_%" mytest.csv) do if exist %%f del %%f
  endlocal & goto :EOF
  '
  '.............................................
  'The Visual Basic Script
  '
  Do While Not WScript.StdIn.AtEndOfStream  'VBS
    str = WScript.StdIn.ReadLine            'VBS
    str = str + ","                         'VBS
    str = Replace (str, ",,",",-,")         'VBS
    str = Replace (str, ",,",",-,")         'VBS
    '
    p1 = Instr (1, str, ",", 1)             'VBS
    str1 = Mid (str, 1, p1-1)               'VBS
    If str1 <> "-" Then                     'VBS
      WScript.StdOut.WriteLine str1         'VBS
      Else                                  'VBS
      WScript.StdOut.WriteLine ".."         'VBS
    End If                                  'VBS
    '
    p2 = Instr (p1+1, str, ",", 1)          'VBS
    str2 = Mid (str, p1+1, p2-p1-1)         'VBS
    If str2 <> "-" Then                     'VBS
      WScript.StdOut.WriteLine str2         'VBS
      Else                                  'VBS
      WScript.StdOut.WriteLine ".."         'VBS
    End If                                  'VBS
    '
    p3 = Instr (p2+1, str, ",", 1)          'VBS
    str3 = Mid (str, p2+1, p3-p2-1)         'VBS
    If str3 <> "-" Then                     'VBS
      WScript.StdOut.WriteLine str3         'VBS
      Else                                  'VBS
      WScript.StdOut.WriteLine ".."         'VBS
    End If                                  'VBS
    '
    WScript.StdOut.WriteLine                'VBS
  Loop                                      'VBS

The output will be
  C:\_D\TEST>cmdfaq
  a11
  a12
  a13

  a21
  ..
  a23

References/Comments:
 http://www.google.com/groups?selm=dh2mr6%24cer%241%40haavi.uwasa.fi
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:01:59 2008
Subject: 119) How can I remove any leading zeros from an unsigned integer?
Date: Thu,  6 Mar 2008 01:01:59
From: ts@uwasa.fi (Timo Salmi)

First try the following and you'll see why this can be important
  @echo off & setlocal enableextensions
  set s_=008
  set /a s_=%s_%+2
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  Invalid number.  Numeric constants are either decimal (17),
  hexadecimal (0x11), or octal (021).

To remove the leading zeros (and leading spaces)
  @echo off & setlocal enableextensions
  set s_= 008
  echo %s_%
  echo %s_%|findstr [123456789]>nul
  if %errorlevel% EQU 0 (
    for /f "tokens=* delims=0 " %%a in ('echo %s_%') do (
      set s_=%%a)
    ) else (set s_=0)
  echo %s_%
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
   008
  8

Or, using a subroutine method
  @echo off & setlocal enableextensions
  set s_=000
  echo %s_%
  call :TrimZeros "%s_%" s_
  echo %s_%
  endlocal & goto :EOF
  ::
  :: =============================================
  :TrimZeros Dymmy1 Return_
  setlocal enableextensions
  echo %~1|findstr [a-zA-Z\.]>nul
  if %errorlevel% EQU 0 (endlocal & set "%2=Error" & goto :EOF)
  echo %1|findstr [123456789]>nul
  if %errorlevel% EQU 0 (
    for /f "tokens=* delims=0 " %%a in ('echo %~1') do (
      set Return_=%%a)
    ) else (set Return_=0)
  endlocal & set "%2=%Return_%" & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  000
  0

Another solution
  @echo off & setlocal enableextensions
  set s_=009
  echo %s_%
  :loop
  if not "%s_%"=="0" if "%s_:~0,1%"=="0" set s_=%s_:~1%&goto loop
  echo %s_%
  endlocal & goto :EOF

Alternatively one could use
  SET N=009
  SET /a N=1%N%-(11%N%-1%N%)/10
  ECHO N=%N%
The output will be
  N=9

References/Comments:
 http://www.google.com/groups?selm=dhdijc%24s5c%241%40haavi.uwasa.fi
 http://www.google.com/groups?selm=1gkwlj8n0alij.uq6pg3ueldok.dlg%4040tude.net
 http://www.google.com/groups?selm=433a8072%241_5%40alt.athenanews.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:00 2008
Subject: 120) How do I use AND/OR/XOR/NOT operators in an IF statement?
Date: Thu,  6 Mar 2008 01:02:00
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  if [%2]==[] (
    echo Usage %~dpn0 var1 var2
    goto :EOF)
  set var1=%~1
  set var2=%~2
  ::
  if "%var1%"=="Timo" if "%var2%"=="Salmi" echo Timo AND Salmi
  ::
  set or_=
  if "%var1%"=="Timo" set or_=true
  if "%var2%"=="Salmi" set or_=true
  if defined or_ echo Timo OR Salmi
  ::
  set xor_=
  if "%var1%"=="Timo" set xor_=true
  if "%var2%"=="Salmi" set xor_=true
  if "%var1%"=="Timo" if "%var2%"=="Salmi" set xor_=
  if defined xor_ echo Timo XOR Salmi
  ::
  if not "%var1%"=="Timo" echo Not Timo
  if not "%var2%"=="Salmi" echo Not Salmi
  ::
  endlocal & goto :EOF

Also see item #102 "How can I extract the individual bits from a
decimal byte?"
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:01 2008
Subject: 121) How do I make a simple reminder to pop up on the desktop?
Date: Thu,  6 Mar 2008 01:02:01
From: ts@uwasa.fi (Timo Salmi)

Below is a simplified version. Only one rendition can be running at
a time. A somewhat more comprehensive version, with multiple calls
allowed, is included in this FAQ collection as WAKEUP.CMD

  @echo off & setlocal enableextensions
  ::
  echo First customize the two instances of C:\_M\TEMP\wakeup.vbs
  echo And remove the first two echo lines and the first goto :EOF
  goto :EOF
  ::
  :: Usage
  if [%1]==[] (
    echo.
    echo Usage: %~f0 [HH:MM]
    echo No error checking
    goto :EOF)
  ::
  :: Build a Visual Basic Script
  set skip=
  set vbs_=C:\_M\TEMP\wakeup.vbs
  findstr "'%skip%VBS" "%~f0" > "%vbs_%"
  ::
  :: Run the Visual Basic Script
  at %1 /interactive "%vbs_%"
  at
  endlocal & goto :EOF
  '
  '.............................................
  'The Visual Basic Script
  '
  Dim WshShell, fso                                                        'VBS
  Set WshShell = WScript.CreateObject("WScript.Shell")                     'VBS
  Set fso = CreateObject("Scripting.FileSystemObject")                     'VBS
  WshShell.Run "sndrec32 /play /close C:\WINDOWS\Media\tada.wav", 2, false 'VBS
  WScript.Echo "Time to wake up"                                           'VBS
  fso.DeleteFile("C:\_M\TEMP\wakeup.vbs")                                  'VBS


A slightly edited example of the immediate output. For more on the
"at" usage apply AT /?
  C:\_D\TEST>cmdfaq 06:15
  Added a new job with job ID = 1
  Status ID   Day         Time    Command Line
          1   Today       06:15   C:\_M\TEMP\wakeup.vbs

The actual output on the desktop looks someting like this
       +--------------------------+
       |  Windows Script Host [X] |
       |--------------------------|
       |                          |
       |  Time to wake up         |
       |                          |
       |     +----------+         |
       |     |    OK    |         |
       |     +----------+         |
       +--------------------------+

Should you wish to cancel the above job before it is executed apply
"AT 1 /delete".
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:02 2008
Subject: 122) How to list files present in folder A but not in folder B?
Date: Thu,  6 Mar 2008 01:02:02
From: ts@uwasa.fi (Timo Salmi)

> I have a folder (Folder A) that has 11,156 files in it.  I have a
> second folder (Folder B) that has 11,121 files in it. I want to
> generate a list of the files that exist in Folder A but not in B.
> How can I do this?

If you have the UNIX port egrep.exe available from UnxUpdates.zip
then it is fairly simple:

  @echo off & setlocal enableextensions
  set folder1_=WhateverA
  set folder2_=WhateverB
  dir /b "%folder1_%">"%temp%\fold1.dir"
  dir /b "%folder2_%">"%temp%\fold2.dir"
  ::
  egrep -v -f "%temp%\fold2.dir" "%temp%\fold1.dir"
  ::
  for %%f in ("%temp%\fold*.dir") do if exist %%f del %%f
  endlocal & goto :EOF

The output might be something like
  C:\_D\TEST>cmdfaq
  BATFAQ.BAS
  BATFAQ.BAT
  BATFAQ2.BAT
  BATFAQ3.BAT
  CMDFAQ2.CMD

With the natural exception of the first and the last line the above
solution is also MS-DOS+Win../95/98/Me compliant.

The task can also be solved with pure script, as below. The solution
has been expanded to include both the NOT and AND cases.

  @echo off & setlocal enableextensions enabledelayedexpansion
  set folder1_=C:\_D\TEST
  set folder2_=C:\_L\TODAY
  ::
  echo.
  echo Files that exist in %folder1_%
  echo but not in %folder2_%
  echo.
  for %%f in ("%folder1_%\*.*") do (
    if not exist "%folder2_%\%%~nxf" (
    set filename_=%%~dpnxf
    set filedate_=%%~tf
    set filesize_=          %%~zf
    set filesize_=!filesize_:~-10!
    echo !filedate_! !filesize_! !filename_!))
  ::
  echo.
  echo Files that exist in %folder1_%
  echo AND in %folder2_%
  echo.
  for %%f in ("%folder1_%\*.*") do (
    if exist "%folder2_%\%%~nxf" (
      set filename_=%%~dpnxf
      set filedate_=%%~tf
      set filesize_=          %%~zf
      set filesize_=!filesize_:~-10!
      echo !filedate_! !filesize_! !filename_!
      ::
      set filename2_=%folder2_%\%%~nxf
      for %%g in ("!filename2_!") do (
        set filename_=%%~dpnxg
        set filedate_=%%~tg
        set filesize_=          %%~zg
        set filesize_=!filesize_:~-10!
        echo !filedate_! !filesize_! !filename_!)
      echo.
      )
    )
  ::
  endlocal & goto :EOF

The output might be something like

  C:\_D\TEST>cmdfaq

  Files that exist in C:\_D\TEST
  but not in C:\_L\TODAY

  19.02.2005 12:52         50 C:\_D\TEST\BATFAQ.BAS
  21.04.2005 00:29        824 C:\_D\TEST\BATFAQ.BAT
  17.04.2005 11:52      21928 C:\_D\TEST\BATFAQ2.BAT
  03.12.2002 07:58         90 C:\_D\TEST\BATFAQ3.BAT
  14.10.2005 17:40      12001 C:\_D\TEST\CMDFAQ2.CMD

  Files that exist in C:\_D\TEST
  AND in C:\_L\TODAY

  29.10.2005 06:58       1255 C:\_D\TEST\CMDFAQ.CMD
  28.10.2005 22:16        317 C:\_L\TODAY\CMDFAQ.CMD
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:03 2008
Subject: 123) How to test if a file is in a folder or below two or more times?
Date: Thu,  6 Mar 2008 01:02:03
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions enabledelayedexpansion
  set startat_=C:\_M
  set filename_=temp48.prn
  ::
  set count_=0
  for /f %%f in ('dir /b /s "%startat_%\%filename_%"') do (
    set /a count_+=1)
  ::
  echo Found %count_% occurrences of %filename_%
  if %count_% GTR 1 (
    for /f %%f in ('dir /b /s "%startat_%\%filename_%"') do (
      set filename_=%%~dpnxf
      set filedate_=%%~tf
      set filesize_=          %%~zf
      set filesize_=!filesize_:~-10!
      echo !filedate_! !filesize_! !filename_!))
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  Found 2 occurrences of temp48.prn
  29.10.2005 07:35       1705 C:\_M\temp48.prn
  29.10.2005 07:35       1705 C:\_M\TEMP\TEMP48.PRN
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:04 2008
Subject: 124) How do I find files which do NOT contain the search string?
Date: Thu,  6 Mar 2008 01:02:04
From: ts@uwasa.fi (Timo Salmi)

Incidentally, this task arose from my own need to check through a
number of html files which I had to edit. I wanted to see if I
missed making one of the intended adjustments.

  @echo off & setlocal enableextensions enabledelayedexpansion
  echo +---------------------------------------------------+
  echo ^| NOFIND.CMD Find files not containing a string     ^|
  echo ^| By Prof. Timo Salmi, Last modified Sun 6-Nov-2005 ^|
  echo +---------------------------------------------------+
  echo.
  ::
  :: Set the appropriate variables
  set string_=%~1
  set source_=%~2
  set ignore_=%~3
  set help_=
  ::
  :: Syntax help, if necessary
  if not defined source_ set help_=true
  if defined ignore_ (
    if /i not "%~3"=="/i" set help_=true
  )
  if defined help_ (
    echo Usage: %~0 "string" "[[drive:][path]filename]" [/i]
    echo Wildcards allowed
    echo Search also subfolders implicitly assumed
    goto :EOF)
  ::
  :: Do the nofind recursively
  for /f %%f in ('dir /b /s "%source_%"') do (
    set file_=%%~dpnxf
    find %ignore_% "%string_%" "!file_!">nul
    if !errorlevel! NEQ 0 echo !file_!
  )
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=436d9c6d%241_2%40alt.athenanews.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:05 2008
Subject: 125) How do I get the age of a file? Or of the files in a folder?
Date: Thu,  6 Mar 2008 01:02:05
From: ts@uwasa.fi (Timo Salmi)

Although the ingredients of this task already are covered here and
there throughout this FAQ, let's revisit this frequent question.
First consider the case of a single file:
  @echo off & setlocal enableextensions
  ::
  :: Usage
  if "%~1"=="" (
    echo Usage: %~0 ["Filename"]
    goto :EOF)
  ::
  :: Check for existence
  if not exist "%~1" (
    echo Target "%~1" not found
    goto :EOF)
  ::
  :: Temporary files
  set vbs_=%temp%\tmp$$$.vbs
  set tmp_=%temp%\tmp$$$.cmd
  ::
  :: Build a Visual Basic Script
  > "%vbs_%" echo Set FSO=CreateObject("Scripting.FileSystemObject")
  >>"%vbs_%" echo sysDate = Date
  >>"%vbs_%" echo Set fname = FSO.GetFile("%~1")
  >>"%vbs_%" echo age = DateDiff("d", fname.DateLastModified, SysDate)
  >>"%vbs_%" echo WScript.Echo "@set age_=" ^& age
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%vbs_%" > "%tmp_%"
  ::
  :: Run the auxiliary cmd script made by vbs
  call %tmp_%
  ::
  :: Display the result
  echo The file "%~1"
  echo is %age_% days old
  ::
  :: Clean up
  for %%f in ("%vbs_%") do if exist %%f del %%f
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq cmdfaq2.cmd
  The file "cmdfaq2.cmd"
  is 14 days old

An aside. The above script fails if given an existing folder as the
parameter instead of a proper file name. How to test for the type
(folder or file) is covered in item #75 if you find it necessary to
include that test.

Next consider traversing all the files in a folder
  @echo off & setlocal enableextensions
  ::
  :: Usage
  if "%~1"=="" (
    echo Usage: %~0 ["[Folder\]FileName"]
    echo Wilcards allowed in the filename
    goto :EOF)
  ::
  :: Traverse an entire folder
  if "%~2"=="recurse" goto _next
  for %%f in ("%~1") do call "%~0" "%%~f" recurse
  goto :EOF
  ::
  :_next
  ::
  :: Temporary files
  set vbs_=%temp%\tmp$$$.vbs
  set tmp_=%temp%\tmp$$$.cmd
  ::
  :: Build a Visual Basic Script
  > "%vbs_%" echo Set FSO=CreateObject("Scripting.FileSystemObject")
  >>"%vbs_%" echo sysDate = Date
  >>"%vbs_%" echo Set fname = FSO.GetFile("%~1")
  >>"%vbs_%" echo age = DateDiff("d", fname.DateLastModified, SysDate)
  >>"%vbs_%" echo WScript.Echo "@set age_=" ^& age
  ::
  :: Run the script with Microsoft Windows Script Host Version 5.6
  cscript //nologo "%vbs_%" > "%tmp_%"
  ::
  :: Run the auxiliary cmd script made by vbs
  call "%tmp_%"
  ::
  :: Display the result
  echo The file "%~1"
  echo is %age_% days old
  ::
  :: Clean up
  for %%f in ("%vbs_%" "%tmp_%") do if exist %%f del %%f
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq "c:\_d\test\*.*"
  The file "c:\_d\test\BATFAQ.BAS"
  is 271 days old
  The file "c:\_d\test\BATFAQ.BAT"
  is 211 days old
  The file "c:\_d\test\BATFAQ2.BAT"
  is 214 days old
  The file "c:\_d\test\BATFAQ3.BAT"
  is 1080 days old
  The file "c:\_d\test\CMDFAQ.CMD"
  is 0 days old
  The file "c:\_d\test\CMDFAQ2.CMD"
  is 14 days old

Finally, what about pinpointing the files that are for example at
least 250 days old? A small modification suffices:
  ::
  :: Display the result
  if %age_% GEQ 250 (
    echo The file "%~1"
    echo is %age_% days old
    )

It is trivial to see that you can put any operation in there. One
very frequently asked questions is "How do I delete files older than
x days with a command line script?". Just insert within the "if"
  del /p "%~1"

References/Comments:
 http://groups.google.com/groups?as_ugroup=alt.msdos.batch.nt&as_q=Remove+files+older+than+X+days
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:06 2008
Subject: 126) How do I grep for a line with a tab?
Date: Thu,  6 Mar 2008 01:02:06
From: ts@uwasa.fi (Timo Salmi)

Dr John Stockton wrote:
>Timo Salmi <ts@uwasa.fi> posted :
>>J Smith wrote:
>>>How do I grep for a line with a tab?
>>>grep "\t" file.txt
>>>does not work

>>Depends on the grep you use. The grep from this one will work as
>>desired in the above
>> 878915 Oct 25 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUpdates.zip

> MiniTrue will do it, expressing the tab either as an actual tab or (in
> the default -x+ state) as \x09.
> At ftp://garbo.uwasa.fi/pc/fileutil/mtr202b.zip

True, if you pardon the feeble pun. Likewise, the more common
G(nu)awk tool could be used. Within a batch file one could have e.g.
    gawk "/\t/{printf \"%%s\n\", $0}" MYFILE.TXT
or, in fact even
  gawk "/\x09/{printf \"%%s\n\", $0}" MYFILE.TXT

Likewise, sed could be used
  sed -n "/\t/p" C:\_M\TEST.TXT
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:07 2008
Subject: 127) How can I pad leading zeros or like to a variable?
Date: Thu,  6 Mar 2008 01:02:07
From: ts@uwasa.fi (Timo Salmi)

The solution already is embedded within a couple of items in this
FAQ, but let's revisit the question and make it a separate item. The
code below adds leading zeros to the replaceable parameter %1 making
it exactly five characters long.
  @echo off & setlocal enableextensions
  set var_=00000%1
  set var_=%var_:~-5%
  echo %var_%
  endlocal & goto :EOF
The output could be e.g.
  C:\_D\TEST>cmdfaq 23
  00023
or
  C:\_D\TEST>cmdfaq 12345678
  45678
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:08 2008
Subject: 128) How to prevent SET /P input from entering the command history?
Date: Thu,  6 Mar 2008 01:02:08
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  set cmdfile=C:\_M\TEMP\temp$$$.cmd
  >  %cmdfile% echo @echo off
  >> %cmdfile% echo set /p var_="Give your input? "
  >> %cmdfile% echo echo %%var_%%
  for %%c in ("cmd /c" del) do %%c %cmdfile%
  endlocal & goto :EOF
Output
  C:\_D\BAS>cmdfaq
  Give your input? Hello World
  Hello World
The "Hello World" is not in the command history.

Or use a call like
  CMD /C myscript.cmd

References/Comments:
 http://www.google.com/groups?selm=43bfd8f0%240%242719%24ed2619ec%40ptn-nntp-reader02.plus.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:09 2008
Subject: 129) Is it possible to stop and reset the print spooler with a script?
Date: Thu,  6 Mar 2008 01:02:09
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  echo Ŀ
  echo  CLRSPOOL.CMD Stop and reset print spooler          
  echo  By Prof. Timo Salmi, Last modified Sun 29-Jan-2006 
  echo 
  ::
  if "%~1"=="?" goto _usage
  if "%~1"=="/?" goto _usage
  ::
  :: The path to the spooler files
  set spool_=C:\WINDOWS\system32\spool\PRINTERS
  ::
  :: Spool contents
  dir "%spool_%"
  echo.
  ::
  :: Ask for confirmation
  set ask_=
  set /p ask_="Reset the print spooler [Y/n]?"
  if /i [%ask_%]==[n] goto _out
  ::
  :: Clear the spooler
  net stop spooler
  for %%f in ("%spool_%\*.*") do (
    if exist "%%f" del "%%f"
    )
  net start spooler
  :: See FAQ item #2 for an explanation of the next line
  dir "%spool_%"
  if not defined cmdbox if defined PauseIfFromDesktop pause
  goto _out
  ::
  :_usage
  echo.
  echo Usage: DELSPOOL
  echo.
  echo High enough user privileges are required to complete this task.
  echo Else the net stop/start commands will just produce error messages.
  goto _out
  ::
  :_out
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:10 2008
Subject: 130) How do I find and delete files which contain a specific text?
Date: Thu,  6 Mar 2008 01:02:10
From: ts@uwasa.fi (Timo Salmi)

> I have a folder which contains about 250000 files.
> File explorer chocks or is slow when I try to search for files
> which contain a certain a certain phrase.
> I would like to delete these files without using a gui program.
> What's the dos syntax to do this in a command prompt?

As by the script solution below. Incidentally, note not explicitly
using the errorlevel.
  @echo off & setlocal enableextensions
  for %%f in ("C:\wherever\*.*") do (
    find /i "whatever" "%%f">nul&&ECHO del "%%f")
  endlocal & goto :EOF

WARNING!
========
The "ECHO" is included for some safety. Careful, as always! Use
scripts with del or other powerful commands at your own risk! A del
from command line or from a script is irreversible.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:11 2008
Subject: 131) How to get the language of Windows XP in a script ?
Date: Thu,  6 Mar 2008 01:02:11
From: ts@uwasa.fi (Timo Salmi)

Matthias Tacke wrote:
> the information provided by foxidrives link includes in one
> posting: reg query "HKEY_CURRENT_USER\Control Panel\International"

That's nicely advanced, while easy to act on.

> It's no big deal to extract portions in a batch.

E.g.
  @echo off & setlocal enableextensions
  for /f "tokens=3" %%i in (
    'reg query "HKEY_CURRENT_USER\Control Panel\International" ^| find "sLanguage"') do (
    set lang_=%%i)
  echo %lang_%
  endlocal & goto :EOF

Which would give for example
  C:\_D\TEST>cmdfaq
  ENU

> http://www.microsoft.com/globaldev/reference/winxp/langtla.mspx

Which, in turns shows
  English - United States ENU 0409

A much less accurate method would be to see what is produced by
  ver /?|find "Windows XP"

Yet another method:
  @echo off & setlocal enableextensions
  for /f "tokens=2 delims=:;" %%i in (
    'systeminfo^|find "System Locale:"') do (
    set lang_=%%i)
  echo %lang_: =%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  en-us

References/Comments:
 http://www.google.com/groups?selm=oj7as1dve5v5%24.es2rzjwjvd1e.dlg%4040tude.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:12 2008
Subject: 132) How to find out the next weekday given today's?
Date: Thu,  6 Mar 2008 01:02:12
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  set  Day=%~1
  set  week=Sun Mon Tue Wed Thu Fri Sat Sun
  call set SubWeek=%%Week:*%day%=%%
  Set  NextDay=%SubWeek:~1,3%
  echo After %Day% comes %NextDay%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq thu
  After thu comes Fri

A similar task for the next character with the Finnish alphabet
  @echo off & setlocal enableextensions
  set letter=%1
  set alpha=abcdefghijklmnopqrstuvwxyza
  call set beta=%%alpha:*%letter%=%%
  set last=%beta:~,1%
  echo After %letter% comes %last%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq 
  After  comes 

References/Comments:
 The inventive method is due to Clay Calvert:
 http://www.google.com/groups?selm=e1j2v1hhog4ncpgc38uebm9jlv4ktn8kp0%404ax.com
Also of interest:
 http://www.jsifaq.com/SF/Tips/Tip.aspx?id=9830
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:13 2008
Subject: 133) How do I get the current IP address, number and name?
Date: Thu,  6 Mar 2008 01:02:13
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  :: Get the current IP
  for /f "tokens=2 delims=:" %%i in (
    'ipconfig /all^|find "IP Address"'
    ) do set ip=%%i
  set ip=%ip: =%
  echo %ip%
  ::
  :: Look up the IP address on the name server
  for /f "tokens=2 delims=:" %%n in (
    'nslookup %ip%^|find "Name:"'
    ) do set name=%%n
  set name=%name: =%
  echo %name%
  endlocal & goto :EOF

The output might be e.g.
  D:\TEST>cmdfaq
  193.166.122.2
  reimari.uwasa.fi
--------------------------------------------------------------------
From ts@uwasa.fi Thu Mar  6 01:02:14 2008
Subject: 134) How do I advance the dates of my certain JPG files by one year?
Date: Thu,  6 Mar 2008 01:02:14
From: ts@uwasa.fi (Timo Salmi)

You'll need a touch utility port e.g. from
 3365706 Apr 15 2003 ftp://garbo.uwasa.fi/win95/unix/UnxUtils.zip
 UnxUtils.zip GNU utilities for native Win32
for the script below.

  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  rem Note, assumes date format DD.MM.YYYY hh:mm
  rem E.g. 21.02.2006 08:14
  ::
  :: Usage
  if "%~1"=="" (
    echo Usage: %~0 [Filename]
    goto :EOF
    )
  :: Check that the file(s) to be restamped exist
  if not exist "%~1" (
    echo File^(s^) "%~1" not found
    goto :EOF
    )
  ::
  :: Store the potential time zone information, and make a note
  if defined tz (
    echo @rem the current timezone TZ is %TZ%
    echo set TZ=
    )
  set storetz=%tz%
  set tz=
  ::
  :: Get the old stamps and display the commands for changing them
  for %%f in ("%~1") do (
    set filename=%%~dpnxf
    set filestamp=%%~tf
    set filedd=!filestamp:~0,2!
    set filemm=!filestamp:~3,2!
    set fileyear=!filestamp:~6,4!
    set filehour=!filestamp:~11,2!
    set filemin=!filestamp:~14,2!
    ::
    set /a fileyear_new=!fileyear! + 1
    echo touch -c -f !filemm!!filedd!!filehour!!filemin!!fileyear_new! !filename!
    )
  ::
  :: Restore the original timezone information
  set tz=%storetz%
  if defined tz echo set TZ=%tz%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq C:\_H\PHOTO\HME2006A\*.JPG
  @rem the current timezone TZ is Europe/Helsinki
  set TZ=
  touch -c -f 011513242007 C:\_H\PHOTO\HME2006A\66011507.JPG
  touch -c -f 020213322007 C:\_H\PHOTO\HME2006A\66020201.JPG
  set TZ=Europe/Helsinki

The above example was for exactly a one year increment. For generic
changes for any number of days from now on, or back, take the needed
additional cues from item #31.

The is a slight catch. The method zeroes the seconds part, since XP
will not display them. E.g. a VBS-aided script, such as my included
"FILEINFO.VBS FileInfo Visual Basic Script" would be needed to get
also the seconds in a file's datestamp.

If you wish to be very orthodox, check that the touch you use knows
how to handle the very rare case of Feb 29 correctly.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:15 2008
Subject: 135) How do I get information about a file extension association?
Date: Thu,  6 Mar 2008 01:02:15
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  if "%~1"=="" (
    echo Usage: %~0 .extension
    goto :EOF
    )
  set ext_=%~1
  ::
  echo %ext_%|find "=" > nul
  if %errorlevel% EQU 0 (
    echo Equal signs not allowed for safety reasons in %ext_%
    goto :EOF
    )
  ::
  for /f "tokens=2 delims==" %%a in (
    'assoc^|find /i "%ext_%"') do set assoc_=%%a
  echo %ext_% %assoc_%
  ::
  if defined assoc_ (
    reg query HKLM\SOFTWARE\Classes\%assoc_%|find "REG_SZ"
    echo.
    reg query HKLM\SOFTWARE\Classes\%assoc_%\shell|find "shell\"
    echo.
    for /f "tokens=1* delims==" %%a in ('assoc %ext_%') do ftype %%b
    ) else (
    echo No association)
  ::
  ::
  endlocal & goto :EOF

The output might be e.g.

  C:\_D\TEST>cmdfaq .html
  .html FirefoxHTML
      AlwaysShowExt       REG_SZ
      <NO NAME>   REG_SZ  HTML Document
  HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FirefoxHTML\shell\Edit_with_Notepad
  HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FirefoxHTML\shell\open
  HKEY_LOCAL_MACHINE\SOFTWARE\Classes\FirefoxHTML\shell\Open_with_Mozilla
  FirefoxHTML=C:\PROGRA~1\MOZILL~1\FIREFOX.EXE -url "%1"

  C:\_D\TEST>cmdfaq .dir
  .dir
  No association

References/Comments:
 http://www.google.com/groups?selm=avpk021kgkf4bnn5ad3eiotk9i5d261luj%404ax.com
 http://www.google.com/groups?selm=pan.2006.03.05.20.03.41.859000%40virgin.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:16 2008
Subject: 136) How do I find out when my PC was last booted?
Date: Thu,  6 Mar 2008 01:02:16
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  for /f "tokens=3,4" %%d in (
    'net statistics workstation^|find "Statistics since"') do (
    set lastboot=%%d %%e
    )
  echo Last booted %lastboot%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  Last booted 11.04.2006 09:17

Alternatively, suggested by Phil Robyn
  @echo off & setlocal enableextensions
  for /f "tokens=1,2" %%d in (
    'dir /ah /s C:\pagefile.sys^|find /i "pagefile.sys"') do (
    set lastboot=%%d %%e
    )
  echo Last booted %lastboot%
  endlocal & goto :EOF

There is yet another way. As it happens, I have the following script
in the Startup folder, which is directly pertinent to the question
discussed:
  @echo off & setlocal enableextensions
  set target_=C:\_L\TIMO\logon.txt
  ::
  color 0B
  echo +-------------------------------+
  echo : Logging the user's logon      :
  echo : A script by Prof. Timo Salmi  :
  echo : Last modified Thu 15-Feb-2007 :
  echo +-------------------------------+
  echo.
  echo %date% %time%
  echo Making an entry to %target_%
  ::
  if not defined temp goto :EOF
  set temp_=%temp%
  if exist c:\_l\temp set temp_=C:\_L\TEMP
  for /f "tokens=*" %%f in ("%temp_%") do set temp_=%%~sf
  ::
  gawk 'BEGIN{printf"@set wd_=%%s\n",strftime("%%a",systime())}'>%temp_%\weekday$.cmd
  for %%c in (call del) do %%c %temp_%\weekday$.cmd
  ::
  echo Logon: %COMPUTERNAME% %wd_% %date% %time% %USERNAME%>%temp_%\logon1.tmp
  if not exist %target_% (
    copy /y %temp_%\logon1.tmp %target_% > nul
    goto _out
    )
  copy %target_% %temp_%\logon2.tmp > nul
  copy /y %temp_%\logon1.tmp + %temp_%\logon2.tmp %target_% > nul
  ::
  :_out
  for %%f in (logon1.tmp logon2.tmp weekday$.cmd) do if exist %temp_%\%%f del %temp_%\%%f
  endlocal & goto :EOF

Alternatively:
  @echo off & setlocal enableextensions
  for /f "tokens=* skip=1" %%i in ('wmic OS Get LastBootUpTime') do (
    set LastBootUpTime=%%i)
  echo LastBootUpTime: %LastBootUpTime%
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=MWk0g.27299%24WI1.12525%40pd7tw2no
 http://www.microsoft.com/ntserver/nts/downloads/management/uptime/default.asp
 http://support.microsoft.com/kb/290216/en-us
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:17 2008
Subject: 137) I need to resize a group of images from the command line.
Date: Thu,  6 Mar 2008 01:02:17
From: ts@uwasa.fi (Timo Salmi)

To do this you need a good image processing program like IrfanView
for WinNT, Win9x, Win2000, WinXP from http://www.irfanview.com/

  @echo off & setlocal enableextensions
  ::
  echo Ŀ
  echo  IRSCALED.CMD Resize a set of .jpg images to 80x60 pixels 
  echo  By Prof. Timo Salmi, Last modified Fri 12-Jan-2007       
  echo 
  echo.
  ::
  :: Set the defaults
  set ir="C:\Program Files\IrfanView\i_view32.exe"
  set sourceDir=C:\_M
  set targetDir=C:\_M\SCALED
  set pixW=80
  set pixH=60
  ::
  :: Is help needed
  if "%~1"=="?" goto _help
  if "%~1"=="/?" goto _help
  if /i "%~1"=="/help" goto _help
  ::
  :: If necessary, create the target folder
  if not exist %targetDir% mkdir %targetDir%
  ::
  :: Corvert with Irfanview command line
  rem Add /aspectratio if you want to force keeping the image proportions
  for %%f in (%sourceDir%\*.JPG) do (
    start "" /wait %ir% %%~ff /resize=^(%pixW%,%pixH%^) /jpgq=75 /convert=%targetDir%\%%~nf.scaled%%~xf
    )
  ::
  :: Show the results
  dir %targetDir%
  goto _out
  ::
  :_help
  echo Usage: IRSCALED
  echo.
  echo Default source folder: %sourceDir%
  echo Default target folder: %targetDir%
  ::
  :_out
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=1dd29q20m7kc9%24.1t7olhjmxvmbs.dlg%40tude.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:18 2008
Subject: 138) How can I get the long name of a short-named file or folder?
Date: Thu,  6 Mar 2008 01:02:18
From: ts@uwasa.fi (Timo Salmi)

Getting the short name of a file or folder is relatively easy with
FOR /F and %%~sI but the reverse is more complicated.

> Is it possible to cd to short-named dir, but prompt to show full,
> long name?

The question essentially is, when in a short-named folder, how can
one get its long name? The solution below should do this, for XP at
least

  @echo off & setlocal enableextensions
  cd C:\DOCUME~1
  for /f %%d in ("%cd%") do set name_=%%~nd
  for /f %%p in ("%cd%") do set path_=%%~dpp
  for /f "tokens=* delims=" %%a in (
    'dir /x ..^|find "%name_%"') do set long_=%%a
  set long_=%long_:~49%
  echo %path_%%long_%
  endlocal & goto :EOF

The output would be
  C:\_M>c:\_d\bas\cmdfaq
  C:\Documents and Settings

More generally:
  @echo off & setlocal enableextensions
  echo.
  echo +----------------------------------------------------+
  echo : Get the long name of a short-named folder or file  :
  echo : By Prof. Timo Salmi. Last modified Fri 28-Apr-2006 :
  echo +----------------------------------------------------+
  echo.
  ::
  :: Usage
  if "%~1"=="" (
    echo Usage: %~f0 "ShortFolderOrFileName"
    goto :EOF
    )
  ::
  :: Check that it is about a short name
  echo "%~1"|find "~">nul
  if %errorlevel% GTR 0 (
    echo "%~1" is not a valid short name
    goto :EOF
    )
  ::
  :: Check the existence
  if not exist "%~1" (
    echo "%~1" not found
    goto :EOF
    )
  ::
  :: Get and process the information
  for /f %%d in ("%~1") do set name_=%%~nd
  for /f %%p in ("%~1") do set path_=%%~dpp
  for /f "tokens=* delims=" %%a in (
    'dir /x "%1\.."^|find "%name_%"') do set long_=%%a
  set long_=%long_:~49%
  ::
  :: Show the results
  echo %~1
  echo %path_%%long_%
  endlocal & goto :EOF

The output might be e.g.
  C:\_M>c:\_d\bas\cmdfaq "C:\_D\BAS\KOE2~1.CMD"
  C:\_D\BAS\KOE2~1.CMD
  C:\_D\BAS\KOE 2.CMD

There is an even simple solution to the problem of displaying the
long-name format of the current folder as captured below

  C:\DOCUME~1>attrib %cd%
             C:\Documents and Settings

Developed from that we get:
  @echo off & setlocal enableextensions
  if "%~1"=="" (
    set dir_=%cd%
    ) else (
    set dir_=%~1
    )
  ::
  echo %dir_%|findstr /e "\\" > nul
  if %errorlevel% EQU 0 (
   echo Drop the trailing backslash \
   goto :EOF)
  ::
  if not exist "%dir_%\" (
   echo "%dir_%" no such folder
   goto :EOF)
  ::
  for /f "tokens=* delims=" %%d in (
    'attrib "%dir_%"') do set long_=%%d
  set long_=%long_:~11%
  ::
  echo %dir_%
  echo %long_%
  endlocal & goto :EOF

The output might be e.g.
  C:\_M>C:\_D\BAS\CMDFAQ C:\DOCUME~1
  C:\DOCUME~1
  C:\Documents and Settings

The problem with the above solutions is that they work one level at
the time only. Thus one has to walk through, which takes some doing.
A fullpath solution to the problem is given below
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Display intermediate information for debugging or not
  set debug=true
  set debug=
  ::
  :: Usage
  if "%~1"=="" (
    echo.
    echo Usage: %~0 [FolderOrFileName]
    goto :EOF
    )
  ::
  :: Give the name of the folder or the file
  set name=%~f1
  if not exist "%name%" (
    echo "%name%" not found
    goto :EOF)
  ::
  :: Parse the path elements
  set count_=0
  set rest_=%name%
  :_loop
  for /f "tokens=1* delims=\" %%a in ("%rest_%") do (
    set /a count_+=1
    set part[!count_!]=%%a
    set rest_=%%b
    if defined rest_ goto _loop
    )
  ::
  :: Display the individual parts
  if defined debug (
    for /l %%i in (1,1,%count_%) do (
      echo part[%%i]=!part[%%i]!
      )
    echo.
    )
  ::
  :: Build up the path
  for /l %%i in (1,1,%count_%) do (
    set longpath_=!longpath_!!part[%%i]!\
    if %%i GTR 1 (
      for /f "tokens=* delims=" %%f in (
        'attrib "!longpath_:~0,-1!"') do (
        set longpath_=%%f
        set longpath_=!longpath_:~11!\
        )
      if defined debug echo !longpath_!
      )
    )
  set longpath_=%longpath_:~0,-1%
  ::
  :: Display the result
  echo The given format was:
  echo %name%
  echo The long format is:
  echo %longpath_%
  ::
  endlocal & goto :EOF

Examples of the output
  C:\_D\BAS>cmdfaq %temp%
  The given format was:
  C:\DOCUME~1\ts\LOCALS~1\Temp
  The long format is:
  C:\Documents and Settings\ts\Local Settings\Temp

  C:\_D\BAS>cmdfaq %temp%\jupdate1.5.0.xml
  The given format was:
  C:\DOCUME~1\ts\LOCALS~1\Temp\jupdate1.5.0.xml
  The long format is:
  C:\Documents and Settings\ts\Local Settings\Temp\jupdate1.5.0.xml

  C:\_D\BAS>cmdfaq C:\DOCUME~1\ts\LOCALS~1
  The given format was:
  C:\DOCUME~1\ts\LOCALS~1
  The long format is:
  C:\Documents and Settings\ts\Local Settings

  C:\_D\BAS>cmdfaq TEST3~1.CMD
  The given format was:
  C:\_D\BAS\TEST3~1.CMD
  The long format is:
  C:\_D\BAS\TEST  3.CMD

References/Comments:
 http://www.google.com/groups?selm=D7q4g.3%24zR3.2%40newssvr33.news.prodigy.com
 http://www.google.com/groups?selm=fq8is2pq03ckcsb4so0d6075bsc2qkud8o%404ax.com
--------------------------------------------------------------------
From ts@uwasa.fi Thu Mar  6 01:02:19 2008
Subject: 139) How do I convert UNIX newlines to PC eolns? And vice versa?
Date: Thu,  6 Mar 2008 01:02:19
From: ts@uwasa.fi (Timo Salmi)

Using SED:
  @echo off & setlocal enableextensions
  rem UNIX newlines to PC eolns
  set source_=C:\_M\UNIX.TXT
  set target_=C:\_M\PC.TXT
  sed -e "s/\x0a/\x0d\x0a/" %source_% > %target_%
  endlocal & goto :EOF
In fact, any "dummy" sed conversion will do:
  sed -e "s/ / /" %source_% > %target_%

Using G(nu)AWK
  @echo off & setlocal enableextensions
  rem UNIX newlines to PC eolns
  set source_=C:\_M\UNIX.TXT
  set target_=C:\_M\PC.TXT
  gawk "BEGIN{RS=\"[\012]\"}{print $0}" %source_% > %target_%
  endlocal & goto :EOF

There naturally also is a number of specialized third-party
utilities to do the conversion, including
 ftp://garbo.uwasa.fi/pc/ts/tsfilt25.zip
 Programs for filtering messages, log files, Unix-PC, etc

The reverse task, i.e. converting PC eolns to UNIX newlines is most
naturally done on the UNIX host e.g. with the following Bourne Shell
script:
 ftp://garbo.uwasa.fi/unix/ts/pc2unix
 Filter PC end of lines to Unix end of lines, T.Salmi

References/Comments:
 http://www.google.com/groups?selm=lgm252lltdge4rqn37i7rvm7ee60op7u8i%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:20 2008
Subject: 140) How do I count how many times a word appears in my text file?
Date: Thu,  6 Mar 2008 01:02:20
From: ts@uwasa.fi (Timo Salmi)

First decompose the original text file so that each word is on a
line of its own. Then get with find the number of lines with the
word appearing.
  @echo off & setlocal enableextensions
  set source_=C:\wherever\MYFILE.TXT
  sed -e "s/[\x20\x09]/\x0d\x0a/g" %source_% > "%temp%\words.tmp"
  for /f "tokens=3" %%c in ('
    find /i /c "mytext" "%temp%\words.tmp"') do set count_=%%c
  echo Found your word %count_% times
  for %%f in ("%temp%\words.tmp") do if exist %%f del %%f
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  Found your word 3 times

Or with G(nu)AWK:
  @echo off & setlocal enableextensions
  gawk "{j=1;while(j<=NF){if($j==\"myword\"){n++};j++};j=1};END{print \"@set count_=\"n}" cmdfaq.cmd>"%temp%\setcount.cmd"
  for %%c in (call del) do %%c "%temp%\setcount.cmd"
  echo Found your word %count_% times
  endlocal & goto :EOF
The gawk solution is more accurate in the sense that it does not
count partial word occurrences. It also is case sensitive.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:21 2008
Subject: 141) Why isn't the ! character always echoed as expected?
Date: Thu,  6 Mar 2008 01:02:21
From: ts@uwasa.fi (Timo Salmi)

This is a result of a side effect. The exclamation mark is used to
expand environment variables at execution time if the delayed
variable expansion is enabled in a script. This affects how the !
character is treated. Note the different outputs in the following
demonstration:

  @echo off
  setlocal enableextensions enabledelayedexpansion
  echo delayed expansion enabled
  echo.WOW!!!
  echo.WOW^!^!^!
  echo.WOW^^!^^!^^!
  echo.! test! addition suggested by foxidrive!
  echo.!test! addition suggested by foxidrive!
  setlocal enableextensions disabledelayedexpansion
  echo.
  echo delayed expansion disabled
  echo.WOW!!!
  echo.WOW^!^!^!
  echo.WOW^^!^^!^^!
  echo.! test! addition suggested by foxidrive!
  echo.!test! addition suggested by foxidrive!
  endlocal & goto :EOF
The output will be
  C:\_D\TEST>cmdfaq
  delayed expansion enabled
  WOW
  WOW
  WOW!!!
   test
   addition suggested by foxidrive

  delayed expansion disabled
  WOW!!!
  WOW!!!
  WOW^!^!^!
  ! test! addition suggested by foxidrive!
  !test! addition suggested by foxidrive!

Browse throughout the items in this FAQ for several examples of
using the delayed expansion for its actual purpose. For example,
consider the task of listing today's files in the current folder.
One of the possible ways of formulating that is
  @echo off & setlocal enableextensions enabledelayedexpansion
  for %%f in ("*.*") do (
    echo "%%~tf" | find "%date%" > nul
    if !errorlevel! EQU 0 echo %%~tf %%~zf "%%~ff"
    )
  endlocal & goto :EOF
The output might be
  C:\_D\TEST>cmdfaq
  20.05.2006 10:10 21928 "C:\_D\TEST\BATFAQ2.BAT"
  20.05.2006 10:22 216 "C:\_D\TEST\CMDFAQ.CMD"

Note !errorlevel! not %errorlevel%.
Incidentally, in this particular case also the following formulation
would work
  if not errorlevel 1 echo %%~tf %%~zf "%%~ff"
but even if important formulation lore that is beside the current
point on delayed expansion.

Aligning the output demontrates further
  @echo off & setlocal enableextensions enabledelayedexpansion
  for %%f in ("*.*") do (
    echo "%%~tf" | find "%date%" > nul
    if not errorlevel 1 (
      set fdate=%%~tf
      set fsize=%%~zf
      set fsize=          !fsize!
      set fsize=!fsize:~-10!
      set fname="%%~ff"
      echo !fdate! !fsize! !fname!
      )
    )
  endlocal & goto :EOF
The output might be
  C:\_D\TEST>cmdfaq
  20.05.2006 10:10      21928 "C:\_D\TEST\BATFAQ2.BAT"
  20.05.2006 10:19        372 "C:\_D\TEST\CMDFAQ.CMD"

A related problem asked in alt.mdsosbatch.nt. Suppose there is a
file C:\WHEREVER\LIST.TXT containing a list of file names such as
  C:\_D\TEST\TEST!.TXT
  C:\_D\TEST\TEST%.TXT

To perform an example operation on those file use the following
kind of syntax
  @echo off & setlocal enableextensions disabledelayedexpansion
  for /f "tokens=*" %%f in ("c:\wherever\list.txt") do type "%%f"
  endlocal & goto :EOF
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:22 2008
Subject: 142) How to extract the filename from the end of an URL reference?
Date: Thu,  6 Mar 2008 01:02:22
From: ts@uwasa.fi (Timo Salmi)

There are several ways of doing this. Consider the following example
where the URL is http://lipas.uwasa.fi/~ts/http/netiquet.html
The easiest of the solutions, posted by Ted Davis et al. is

  @echo off & setlocal enableextensions
  set url_=http://lipas.uwasa.fi/~ts/http/netiquet.html
  for %%a in (%url_%) do set filename_=%%~nxa
  echo %filename_%
  endlocal & goto :EOF
The output would be
  C:\_D\TEST>cmdfaq
  netiquet.html

Note that if there are spaces (not a good idea in an URL), the URL
has to be enclosed in quotes.

There is an interesting corollary. The method can also be used to
get the last word on a line. For example
  @echo off & setlocal enableextensions
  set line_=Hello World and Ted Davis
  for %%a in (%line_%) do set line_=%%~nxa
  echo %line_%
  endlocal & goto :EOF
will give
  C:\_D\TEST>cmdfaq
  Davis

However, consider
  @echo off & setlocal enableextensions
  set line_=Hello World and Harlan Grove.
  for %%a in (%line_%) do set line_=%%~a
  echo %line_%
  for %%a in (%line_%) do set line_=%%~nxa
  echo %line_%
  endlocal & goto :EOF
Note the differences in the output
  C:\_D\TEST>cmdfaq
  Grove.
  Grove

References/Comments:
 http://www.google.com/groups?selm=447e0ff0%240%2422334%249b536df3%40news.fv.fi
 http://www.google.com/groups?selm=vgds729t5hg6nfpb9ef3f5fos15q533olq%404ax.com
 http://www.google.com/groups?selm=1149140236.288371.157450%40g10g2000cwb.googlegroups.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:23 2008
Subject: 143) How do I get the current time zone in a script?
Date: Thu,  6 Mar 2008 01:02:23
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  :: Get the time zone in minutes
  for /f "tokens=5" %%a in (
    'w32tm /tz^|find "Time zone"') do set TZbias=%%a
  for /f "tokens=1 delims=m" %%a in (
    'echo %TZbias%') do set TZbias=%%a
  ::
  :: Display the result in minutes
  echo Bias: %TZbias% minutes
  ::
  :: Display the result in hours
  set /a TZfrac=%TZbias%%%60*100/60
  if %TZfrac% LSS 0 set /a TZfrac=-%TZfrac%
  set /a TZbias=-%TZbias%/60
  echo UTC+(%TZbias%.%TZfrac%)
  endlocal & goto :EOF

The output for my own computer's time zone (Europe/Helsinki) is
  C:\_D\TEST>cmdfaq
  Bias: -120 minutes
  UTC+(2.0)

Alternatively, in XP and beyond
  @echo off & setlocal enableextensions
  for /f "tokens=* skip=1" %%i in ('wmic OS Get CurrentTimeZone') do (
    set CurrentTimeZone_=%%i)
  echo CurrentTimeZone: %CurrentTimeZone_% minutes
  endlocal & goto :EOF

The output for my own computer's time zone (Europe/Helsinki) in the
summer is
  C:\_D\TEST>cmdfaq
  CurrentTimeZone: 180               minutes

Another method:
  @echo off & setlocal enableextensions
  for /f "tokens=2,*" %%i in ('systeminfo^|findstr /b "Time Zone:"') do (
    set tz_=%%j)
  echo %tz_%
  for /f "tokens=1" %%i in ('echo "%tz_%"') do set tz_=%%~i
  set tz_=%tz_:(=%
  set tz_=%tz_:)=%
  echo %tz_%
  endlocal & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq
  (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius
  GMT+02:00
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:24 2008
Subject: 144) How do I parse the items from a path like C:\a\b\c\d ?
Date: Thu,  6 Mar 2008 01:02:24
From: ts@uwasa.fi (Timo Salmi)

Edited from the original question by Bob Altman in
alt.msdos.batch.nt

I call a batch file like this:  DoSomething c:\a\b\c\d
I need to parse the specified path and execute a command for each
folder in the path containing the specified file.  The order of
execution doesn't matter.  So, for the above example, I need to do
the following:
  SomeCommand c:\a
  SomeCommand c:\a\b
  SomeCommand c:\a\b\c

With a generic rather than customized parsing view we can use e.g.
  @echo off & setlocal enableextensions enabledelayedexpansion
  set var=C:\a\b\c\d
  rem the above might alternatively be:
  rem set var=%~1
  ::
  :: Parse
  set count_=0
  set rest_=%var%
  :_loop
  for /f "tokens=1* delims=\" %%a in ("%rest_%") do (
    set /a count_+=1
    set var[!count_!]=%%a
    set rest_=%%b
    if defined rest_ goto _loop
    )
  ::
  :: Display the individual parts
  for /l %%i in (1,1,%count_%) do echo var[%%i]=!var[%%i]!
  echo.
  ::
  :: Display combined
  for /l %%i in (1,1,%count_%) do (
    set composite_=!composite_!!var[%%i]!\
    if %%i GTR 1 echo Whatever !composite_:~0,-1!
    )
  ::
  endlocal & goto :EOF

The output would be
  C:\_D\TEST>cmdfaq
  var[1]=C:
  var[2]=a
  var[3]=b
  var[4]=c
  var[5]=d

  Whatever C:\a
  Whatever C:\a\b
  Whatever C:\a\b\c
  Whatever C:\a\b\c\d

Also see the items
  80} How can I extract the last part of a path such as C:\ABC\DEF\GHI\?
 115} How can I decompose the path to be one folder per line?

Note how the solution also gives the method for counting the number
of words in a variable or on a line
  @echo off & setlocal enableextensions
  set var=%~1
  ::
  :: Parse and count
  set count_=0
  set rest_=%var%
  :_loop
  for /f "tokens=1*" %%a in ("%rest_%") do (
    set /a count_+=1
    set rest_=%%b
    if defined rest_ goto _loop
    )
  ::
  :: Display the result
  echo.%var%
  echo The number of words is %count_%
  endlocal & goto :EOF

For example
  C:\_D\TEST>cmdfaq "Asterisk means the remaining text on the line"
  Asterisk means the remaining text on the line
  The number or words is 8

The solution also gives the method to get the last word of a line:
  @echo off & setlocal enableextensions
  set var=%~1
  ::
  :: Parse
  set rest_=%var%
  :_loop
  for /f "tokens=1*" %%a in ("%rest_%") do (
    set rest_=%%b
    set last_=%%a
    if defined rest_ goto _loop
    )
  ::
  :: Display the result
  echo.%var%
  echo The last word is "%last_%"
  endlocal & goto :EOF

For example
  C:\_D\TEST>cmdfaq "Asterisk means the remaining text on the line"
  Asterisk means the remaining text on the line
  The last word is "line"
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:25 2008
Subject: 145) How to find out if WinXP SP2 is installed via a script?
Date: Thu,  6 Mar 2008 01:02:25
From: ts@uwasa.fi (Timo Salmi)

The information is in the registry
  @echo off & setlocal enableextensions
  ::
  :: Get the Operating System
  for /f "tokens=2,*" %%i in (
  'reg query "HKLM\software\microsoft\windows nt\currentversion" /v ProductName^
    ^| find "REG_SZ"') do set prod_=%%j
  echo.%prod_%
  ::
  :: Get the service pack version
  for /f "tokens=2,*" %%i in (
  'reg query "HKLM\software\microsoft\windows nt\currentversion" /v CSDVersion^
    ^| find "REG_SZ"') do (
    set pack_=%%j)
  echo.%pack_%
  endlocal & goto :EOF

The output would be something like
  C:\_D\TEST>cmdfaq
  Microsoft Windows XP
  Service Pack 2

Alternatively
  @echo off & setlocal enableextensions
  ::
  :: Get the Operating System
  for /f "tokens=2,*" %%i in (
  'reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v ProductName^
    ^| find "REG_SZ"') do set prod_=%%j
  echo.%prod_%
  ::
  :: Get the service pack version
  for /f "tokens=2,*" %%i in (
    'reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v CSDVersion^
    ^| find "REG_SZ"') do (
    set pack_=%%j)
  echo.%pack_%
  endlocal

Another method, in XP and beyond is to use WMIC (Windows Management
Instrumentation Command-Line Utility)
  @echo off & setlocal enableextensions
  for /f "tokens=* skip=1" %%i in ('wmic OS Get CSDVersion') do (
    set pack_=%%i)
  echo.%pack_%
  endlocal & goto :EOF

The output would be something like
  C:\_D\TEST>cmdfaq
  Service Pack 2

Or
  @echo off & setlocal enableextensions
  for /f "tokens=* skip=1" %%i in ('wmic OS Get ServicePackMajorVersion') do (
    set packMajor_=%%i)
  for /f "tokens=* skip=1" %%i in ('wmic OS Get ServicePackMinorVersion') do (
    set packMinor_=%%i)
  echo.%packMajor_: =%.%packMinor_: =%
  endlocal & goto :EOF

The output would be something like
  C:\_D\TEST>cmdfaq
  2.0

Another option
  @echo off & setlocal enableextensions
  systeminfo | findstr /b "OS.*Pack.2"  && echo SP2 installed
  endlocal & goto :EOF

The output would be something like
  C:\_D\TES>cmdfaq
  OS Version:                5.1.2600 Service Pack 2 Build 2600
  SP2 installed

References/Comments:
 http://www.google.com/groups?selm=t3dcd21657sj9jrilgqvdmdbmgsdliskq2%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:26 2008
Subject: 146) Using delayed expansion for giving variable values as arguments
Date: Thu,  6 Mar 2008 01:02:26
From: ts@uwasa.fi (Timo Salmi)

Consider the following snippet
  @echo off & setlocal enableextensions enabledelayedexpansion
  set i=2&set j=4
  echo %i% %j%
  rem        1234567890
  set string=abcdefghij
  echo %string%
  echo !string:~%i%,%j%!
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  2 4
  abcdefghij
  cdef

An alternative solution, not needing explicit delayed extension, is
  @echo off & setlocal enableextensions
  set i=2&set j=4
  echo %i% %j%
  rem        1234567890
  set string=abcdefghij
  echo %string%
  call set s_=%%string:~%i%,%j%%%
  echo %s_%
  echo.
  endlocal & goto :EOF
The output will be exactly the same.
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:27 2008
Subject: 147) What was the time 100 minutes ago?
Date: Thu,  6 Mar 2008 01:02:27
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  ::
  rem The 24h time format is assumed
  rem as always is sensible in an international setting
  ::
  :: Get the current time: hour and minutes
  for /f "tokens=1,2 delims=:" %%a in ('time /t') do (
    set hhNow_=%%a
    set mmNow_=%%b
    )
  :: Remove any leading zeros to avoid the octal trap
  for /f "tokens=* delims=0" %%a in ('echo %hhNow_%') do set hhNow_=%%a
  for /f "tokens=* delims=0" %%b in ('echo %mmNow_%') do set mmNow_=%%b
  ::
  :: Current time in minutes since midnight
  set /a mmSinceMidnight=60*%hhNow_%+%mmNow_%
  ::
  :: Display
  echo hhNow_ %hhNow_%
  echo mmNow_ %mmNow_%
  echo mmSinceMidnight %mmSinceMidnight%
  ::
  :: How many minutes to calculate backwards?
  set back_=0
  set rollover=
  set OutOfRange=
  if not "%~1"=="" set back_=%1
  if %back_% GTR 1440 set OutOfRange=true
  if %back_% LSS    0 set OutOfRange=true
    if defined OutOfRange (
      echo Parameter %back_% out of range
      goto :EOF
      )
    )
  ::
  :: How many minutes since midnight was back_ minutes ago?
  set /a backSinceMidnight=%mmsinceMidnight%-%back_%
  if %backSinceMidnight% LSS 0 (
    set /a backSinceMidnight=%backSinceMidnight%+24*60
    set rollover=true
    )
  :: Display
  echo backSinceMidnight %backSinceMidnight%
  ::
  :: Convert the result to hours and minutes
  set /a hhBack_=%backSinceMidnight%/60
  set /a mmBack_=%backSinceMidnight%-60*%hhBack_%
  ::
  :: Display
  echo hhBack_ %hhBack_%
  echo mmBack_ %mmBack_%
  if defined rollover echo Yesterday
  ::
  endlocal & goto :EOF

The output e.g.
  C:\_D\TEST>cmdfaq 100
  hhNow_ 9
  mmNow_ 33
  mmSinceMidnight 573
  backSinceMidnight 473
  hhBack_ 7
  mmBack_ 53
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:28 2008
Subject: 148) How to calculate the day-of-year number with a pure cmd script?
Date: Thu,  6 Mar 2008 01:02:28
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions disabledelayedexpansion
  if "%~3"=="" (
    echo Usage: %~0 DD MM YYYY
    echo No leading zeros!
    goto :EOF)
  ::
  :: Get the date
  set day=%~1
  set month=%~2
  set year=%~3
  ::
  :: Call the day ordinal number subroutine
  call :JDdayNumber %day% %month% %year% DayOrdinalNumber
  ::
  :: Display the result
  echo %day%.%month%.%year% Day ordinal number %DayOrdinalNumber%
  endlocal & goto :EOF
  ::
  :: ============================================================
  :: Subroutine: Calculate a day's ordinal number within the year
  :JDdayNumber day month year return_
  setlocal enableextensions enabledelayedexpansion
  if %2 LEQ 2 (
    set /a f=%1-1+31*^(%2-1^)
    ) else (
    set /a a=%3
    set /a b=!a!/4-!a!/100+!a!/400
    set /a c=^(!a!-1^)/4-^(!a!-1^)/100+^(!a!-1^)/400
    set /a s=!b!-!c!
    set /a f=%1+^(153*^(%2-3^)+2^)/5+58+!s!
    )
  set /a return_=%f%+1
  endlocal & set "%4=%return_%" & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq 17 9 2006
  17.9.2006 Day ordinal number 260

(Also see DATEINFO.CMD)

An alternative, more concise formulation of the ordinal day subroutine
  ::
  :: ============================================================
  :: Subroutine: Calculate a day's ordinal number within the year
  :: Based on a posting by Herbert Kleebauer
  :JDdayNumber d m y w
  setlocal enableextensions disabledelayedexpansion
  set /a w= %1 +(!(%3 %% 4)-!(%3 %% 100)+!(%3 %% 400))*(!((%2-3)^&16))
  set /a w=(%w%+(%2-1)*30+2*(!((%2-7)^&16))-1+((65611044^>^>(2*%2))^&3))
  endlocal & set "%4=%w%" & goto :EOF

In the above
  !  Unary NOT operator
  &  Bitwise AND
  %% Remainder (modulo) operator
  >> Logical shift

References/Comments:
 Also see item #70.
 http://www.tondering.dk/claus/cal/node8.html#SECTION00880000000000000000
 http://www.google.com/groups?selm=45015682.E2869E86%40unibwm.de
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:29 2008
Subject: 149) How to calculate a date's week number with a pure cmd script?
Date: Thu,  6 Mar 2008 01:02:29
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions disabledelayedexpansion
  if "%~3"=="" (
    echo Usage: %~0 DD MM YYYY
    echo No leading zeros!
    goto :EOF)
  ::
  :: Get the date
  set day=%~1
  set month=%~2
  set year=%~3
  ::
  :: Call the day ordinal number subroutine
  call :JDweekNumber %day% %month% %year% WeekNumber
  ::
  :: Display the result
  echo %day%.%month%.%year% Week number %WeekNumber%
  endlocal & goto :EOF
  ::
  :: =====================================
  :: Subroutine: Calculate the week number
  :: The weeks in the algorithm start on Mondays
  :JDweekNumber day month year return_
  setlocal enableextensions enabledelayedexpansion
  if %2 LEQ 2 (
    set /a a=%3-1
    set /a b=!a!/4-!a!/100+!a!/400
    set /a c=^(!a!-1^)/4-^(!a!-1^)/100+^(!a!-1^)/400
    set /a s=!b!-!c!
    set /a e=0
    set /a f=%1-1+31*^(%2-1^)
    ) else (
    set /a a=%3
    set /a b=!a!/4-!a!/100+!a!/400
    set /a c=^(!a!-1^)/4-^(!a!-1^)/100+^(!a!-1^)/400
    set /a s=!b!-!c!
    set /a e=!s!+1
    set /a f=%1+^(153*^(%2-3^)+2^)/5+58+!s!
    )
  set /a g=(%a%+%b%) %% 7
  set /a d=(%f%+%g%-%e%) %% 7
  set /a n=%f%+3-%d%
  set return_=
  if %n% LSS 0 set /a return_=53
  if %n% GTR 364+%s% set /a return_=1
  if not defined return_ set /a return_=%n%/7+1
  endlocal & set "%4=%return_%" & goto :EOF

The output might be e.g.
  C:\_D\TEST>cmdfaq 17 9 2006
  17.9.2006 Week number 37
  C:\_D\TEST>cmdfaq 18 9 2006
  18.9.2006 Week number 38
Note that 17.9.2006 is a Sunday and 18.9.2006 a Monday.

(Also see DATEINFO.CMD)

References/Comments:
 http://www.tondering.dk/claus/cal/node8.html#SECTION00880000000000000000
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:30 2008
Subject: 150) How can I extract the http and ftp URL:s from an HTML file?
Date: Thu,  6 Mar 2008 01:02:30
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Get the name of the HTML file to be processed
  set Source=%~1
  if not defined Source (
    echo +----------------------------------------------------+
    echo ^| A script to get the HTTP, FTP and FILE links       ^|
    echo ^| from an HTML page soure file                       ^|
    echo ^| By Prof. Timo Salmi, Last modified Thu 15-Feb-2007 ^|
    echo +----------------------------------------------------+
    echo.
    echo Usage %~0 [HTMLSourceFilename]
    goto :EOF)
  if not exist "%Source%" (
    echo File "%Source%" not found
    goto :EOF)
  ::
  :: An auxiliary temporary file
  set temp_=%temp%
  if defined mytemp set temp_=%mytemp%
  for /f "tokens=*" %%f in ("%temp_%") do set temp_=%%~sf
  set tempfile=%temp_%\tempfile.tmp
  set tempfil2=%temp_%\tempfil2.tmp
  for %%f in (%tempfile% %tempfil2%) do if exist %%f del %%f
  ::
  :: Substitute = with , since tokens does not work with =
  :: Customize the delim character if necessary
  set delim=,
  for /f "tokens=*" %%c in ('type "%Source%"') do (
    set lineContents=%%c
    echo !lineContents:"=%delim%!
    )>>%tempfile%
  ::
  :: Find the HTTP links
  for /f "tokens=2 delims=%delim%" %%a in ('
    find /i "HREF=%delim%http://" %tempfile%') do (
      echo %%a
      )>>%tempfil2%
  type %tempfil2%|find /i "http://"
  ::
  :: Find the FILE links
  for /f "tokens=2 delims=%delim%" %%a in ('
    find /i "HREF=%delim%file://" %tempfile%') do (
      echo %%a
      )>>%tempfil2%
  type %tempfil2%|find /i "file://"
  ::
  :: Find the FTP links
  for /f "tokens=2 delims=%delim%" %%a in ('
    find /i "HREF=%delim%ftp://" %tempfile%') do (
      echo %%a
      )>>%tempfil2%
  type %tempfil2%|find /i "ftp://"
  ::
  :: Clean up
  for %%f in (%tempfile% %tempfil2%) do if exist %%f del %%f
  endlocal & goto :EOF

The output from my own home page's source would start with
  http://www.uwasa.fi/
  http://lipas.uwasa.fi/~ts/timo97.html
  http://www.uwasa.fi/laskentatoimi/
  http://www.uwasa.fi/kauppatieteet/
  http://www.uwasa.fi/
  http://www.vaasa.fi/
  http://en.wikipedia.org/wiki/Finland
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:31 2008
Subject: 151) Extract the lines of a text file from between to marker-lines?
Date: Thu,  6 Mar 2008 01:02:31
From: ts@uwasa.fi (Timo Salmi)

> I have a text file that is like:
>
> date = OCT0606
> asdf
> sdaf
> asdfasdgsdgh
> asdfsdfasdg
> START-OF-DATA
> asdfasdfg
> asdfgdfgsfg
> sadfsdfgsa
> asdfgsdfg
> END-OF-DATA
> asdfgalsdkdfklmlkm
> asdfgasdfg
>
> I need to clear everything from this file except the data between
> the START-OF-DATA and END-OF-DATA using a batch file.

  @echo off & setlocal enableextensions enabledelayedexpansion
  set source=C:\_M\MyData.txt
  set flagStart=
  set flagEnd=
  for /f %%a in ('type "%source%"') do (
    echo %%a|find "START-OF-DATA">nul
    if !errorlevel! EQU 0 set flagStart=true
    echo %%a|find "END-OF-DATA">nul
    if !errorlevel! EQU 0 set flagEnd=true
    if defined flagStart if not defined FlagEnd (
      echo %%a|find /v "START-OF-DATA"
      )
    )
  endlocal & goto :EOF

Actually the lines
  set flagStart=
  set flagEnd=
are superfluous, but they depict the logic.

The output
  C:\_D\TEST>cmdfaq
  asdfasdfg
  asdfgdfgsfg
  sadfsdfgsa
  asdfgsdfg

Also as below. The first is inclusive, the second exclusive
  sed -n "/START-OF-DATA/,/END-OF-DATA/p" %source%
  sed "1,/START-OF-DATA/d" %source%|sed "/END-OF-DATA/,$d"

A batch driven VBS solution can be found e.g. at
 http://www.google.com/groups?selm=BIyWg.8911%24TV3.4248%40newssvr21.news.prodigy.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:32 2008
Subject: 152) How can I remove all !:s and &:s from a text file with a script?
Date: Thu,  6 Mar 2008 01:02:32
From: ts@uwasa.fi (Timo Salmi)

Special characters among &()[]{}^=;!'+,`~ in a text file may cause
problems when the text file is processed with a CLI script. A SED
solution can be used:
  sed -e "s/[\x21\x26]//g" C:\_M\MyText.txt
The character code values are in hexadecimal. Given a text file like
  Hello World & others! Scripting is fun!
the output would be
 Hello World  others Scripting is fun

Another situation applying SED. Say that you wished to substitute
all the @ characters with %40 in a file. Then
  @echo off
  sed -e "s/@/%%40/g" C:\_M\MyText.txt
Note the double %%40 within a script

For example if you had in MyText.txt
  http://www.google.com/groups?selm=452eb6b4%240%2416513%249b536df3@news.fv.fi
then the outcome would be
  http://www.google.com/groups?selm=452eb6b4%240%2416513%249b536df3%40news.fv.fi
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:33 2008
Subject: 153) How do I test if my Internet connection to an IP is working?
Date: Thu,  6 Mar 2008 01:02:33
From: ts@uwasa.fi (Timo Salmi)

There are so many different ways of writing a code. Here is one of
the many alternatives in XP
   @echo off & setlocal enableextensions
   set ok_=true
   ping -n 1 %1|find "Lost = 0">nul||set ok_=
   if defined ok_ (
    echo You have an active connection to %1
    ) else (
    echo You have NO active connection to %1
    )
   endlocal & goto :EOF

However, since ping returns an errorlevel directly, at least in XP,
one can also write
   @echo off & setlocal enableextensions
   ping -n 1 194.109.6.66>nul
   if %errorlevel% EQU 0 (
    echo You have an active connection to the internet
    ) else (
    echo You have NO active connection to the internet
    )
   endlocal & goto :EOF

Output
  C:\_D\TEST>cmdfaq www.google.com
  You have an active connection to www.google.com

Alternatively, just
  @echo off & setlocal enableextensions
  (ping %1>nul && echo Success) || echo Failure
  endlocal & goto :EOF

Output
  C:\_D\TEST>cmdfaq www.google.com
  Success
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:34 2008
Subject: 154) How do I remove leading zeros from a string with script only?
Date: Thu,  6 Mar 2008 01:02:34
From: ts@uwasa.fi (Timo Salmi)

Removing leading zeros (or whatever) from a string is somewhat
different from removing the leading zeros from an unsigned integer
explained in FAQ item #119 "How can I remove any leading zeros from
an unsigned integer?" Also, tThis time we would wish not to use any
third party programs like sed as in the FAQ item #79 "How can I trim
leading and trailing spaces?"

Also note that any zeros within the string should not be removed,
only the leading ones! (Removing all the zeros would be trivial
using the %var:0=% substitution.)

  @echo off & setlocal enableextensions enabledelayedexpansion
  set oldValue=00this is a 0 test
  call :RemoveLeadingZeros "%oldValue%" newValue
  echo "%oldValue%"
  echo "%newValue%"
  endlocal & goto :EOF
  ::
  :RemoveLeadingZeros
  setlocal
  set s=%~1
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if defined si (
      if not "!si!"=="0" set Flag=true
      if defined Flag set return_=!return_!!si!
      )
    )
  endlocal & set "%2=%return_%" & goto :EOF

The output should and will be
  C:\_D\TEST>cmdfaq
  "00this is a 0 test"
  "this is a 0 test"

Let's consider an application for this method from an adapted
question posed in alt.msdos.batch.nt. Suppose that there are files
like the following in a folder
  00000001.TIF
  00000002.TIF
  00000003.TIF
  :
  00000010.TIF
  00000011.TIF
and we wish to rename those files to be without the leading zeros.
The script can then be written (with echo as a safety) as
  @echo off & setlocal enableextensions enabledelayedexpansion
  for /f "tokens=* delims=" %%f in ('dir /s /b /a:-d-s-h 0*.TIF') do (
    set oldFullPathAndFileName=%%~dpnxf
    set oldFileName=%%~nxf
    call :RemoveLeadingZeros "!oldFileName!" fileNameWithoutZeros
    echo ren "!oldFullPathAndFileName!" "!fileNameWithoutZeros!"
    )
  ::
  endlocal & goto :EOF
  ::
  :RemoveLeadingZeros
  setlocal
  set s=%~1
  for /l %%c in (0,1,255) do (
    set si=!s:~%%c,1!
    if defined si (
      if not "!si!"=="0" set Flag=true
      if defined Flag set return_=!return_!!si!
      )
    )
  ::
  endlocal & set "%2=%return_%" & goto :EOF

The output will be:
  C:\_D\TEST>cmdfaq
  ren "C:\_D\TEST\00000001.tif" "1.tif"
  ren "C:\_D\TEST\00000002.tif" "2.tif"
  ren "C:\_D\TEST\00000003.tif" "3.tif"
  :
  ren "C:\_D\TEST\00000010.tif" "10.tif"
  ren "C:\_D\TEST\00000011.tif" "11.tif"
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:35 2008
Subject: 155) How can I use command-line to open a Windows Explorer Window?
Date: Thu,  6 Mar 2008 01:02:35
From: ts@uwasa.fi (Timo Salmi)

E.g. the following command
  Explorer /n,"C:\Documents and Settings"
will open a normal folder window view to C:\Documents and Settings
  Explorer /e,/select,C:\WINDOWS\system32\cmd.exe
will open an extended folder window with cmd.exe selected.

References/Comments:
 http://support.microsoft.com/kb/314853/en-us
 http://support.microsoft.com/kb/307856/en-us
 http://support.microsoft.com/kb/555305/en-us
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:36 2008
Subject: 156) How does one create a shortcut using the command-line?
Date: Thu,  6 Mar 2008 01:02:36
From: ts@uwasa.fi (Timo Salmi)

"Create a shortcut from the command line, K.Yabumoto Pixelab"
See the references.

References/Comments:
 http://www.xxcopy.com/xxcopy38.htm
 ftp://garbo.uwasa.fi/win95/dosshell/xxmklink.zip
 http://www.google.com/groups?selm=epak2l.3f8.1%40news.tacke.de
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:37 2008
Subject: 157) How to get the count of words and the last word of a variable?
Date: Thu,  6 Mar 2008 01:02:37
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  set var=This is my test
  call :GetLast "%var%" lastword nr
  ::
  :: Display the result
  echo.%var%
  echo The number of words is %nr%
  echo The last word is "%lastword%"
  endlocal & goto :EOF
  ::
  :GetLast
  setlocal
  set rest_=%~1
  :_loop
  for /f "tokens=1*" %%a in ("%rest_%") do (
    set /a count_+=1
    set rest_=%%b
    set last_=%%a
    if defined rest_ goto _loop
    )
  endlocal & set "%2=%last_%" & set "%3=%count_%" & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  This is my test
  The number of words is 4
  The last word is "test"

Note the following, obvious twist
  @echo off & setlocal enableextensions
  set var=This is, my test
  call :GetLast "%var%" lastword nr
  ::
  :: Display the result
  echo.%var%
  echo The number of words is %nr%
  echo The last word is "%lastword%"
  endlocal & goto :EOF
  ::
  :GetLast
  setlocal
  set rest_=%~1
  :_loop
  for /f "tokens=1* delims=," %%a in ("%rest_%") do (
    set /a count_+=1
    set rest_=%%b
    set last_=%%a
    if defined rest_ goto _loop
    )
  endlocal & set "%2=%last_%" & set "%3=%count_%" & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq
  This is, my test
  The number of words is 2
  The last word is " my test"

Consider an application with several twists. A user wrote (suitably
edited here) in alt.msdos.batch.nt

I (the said user) have this On_Call.txt file with the following
information
  22.01.2007     John Doe           John.doe@mytest.com
  9991234567@mytest.com
  22.01.2007     Yo C.J. Joe         Yo.Joe@mytest.com
  9991236789@mytest.com
  29.01.2007     Mary Jane         Mary.Jane@mytest.com
  9994567890@mytest.com
  29.01.2007     John Jon            John.jon@mytest.com
  9997890123@mytest.com
  05.02.2007     Tina Turner       Tina.Turner@mytest.com
  9998901234@mytest.com
  05.02.2007     Ike Turner         Ike.Turner@mytest.com
  9999012345@mytest.com

I need help with a script to read this file and only pull the email
address and pager number and write them or export to another file
based on the date. I have two files called email.txt which only has
email address and pager.txt that has only the pager number it.
Incidently, the above file is automatically generated by another
system and saved as a text file in the above format.

So lets say that today is 22.01.2007, the script would run and only
export from the above file John.doe@mytest.com and Yo.Joe@mytest.com
and write them to the email.txt file and then take the pager numbers
9991234567@mytest.com and 9991236789@mytest.com and write them to
the pager.txt file.

This is Timo's solution
  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Delete the old situation, if need be. Else not.
  if exist email.txt del email.txt
  if exist pager.txt del pager.txt
  ::
  set today=%date%
  for /f "tokens=*" %%a in ('type On_Call.txt') do (
    set /a count+=1
    set /a mod=!count!%%2
    if !mod! EQU 1 (
      set entireline=%%a
      set flag=
      for /f "tokens=1" %%a in ('echo !entireline!') do (
        if "%%a"=="%today%" set flag=true
        )
      if defined flag (
        call :GetLast "!entireline!" lastword
        echo !lastword!
        )>>email.txt
      )
    if defined flag if !mod! EQU 0 echo %%a>>pager.txt
    )
  ::
  :: Display the results
  type email.txt
  echo.
  type pager.txt
  endlocal & goto :EOF
  ::
  :: The subroutine for getting the last item on a line
  :GetLast
  setlocal
  set rest_=%~1
  :_loop
  for /f "tokens=1*" %%a in ("%rest_%") do (
    set rest_=%%b
    set last_=%%a
    if defined rest_ goto _loop
    )
  endlocal & set "%2=%last_%" & goto :EOF

The test output
  C:\_M>test.cmd
  John.doe@mytest.com
  Yo.Joe@mytest.com

  9991234567@mytest.com
  9991236789@mytest.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:38 2008
Subject: 158) Why won't the statements within my if condition work properly?
Date: Thu,  6 Mar 2008 01:02:38
From: ts@uwasa.fi (Timo Salmi)

There are several examples throughout this FAQ about for loops which
require delayed expansion. The need for delayed expansion is,
however, not limited to for loops. Below is an artificial example
reminding the reader that the operations within an if statement have
the same feature:

  @echo off & setlocal enableextensions
  set par1=%1
  if "%par1%"=="a" (
    set par2=%2
    echo %par2%
    )
  endlocal & goto :EOF

The output will be
  C:\_D\TEST>cmdfaq a b c d
  ECHO is off.

However, written appropriately
  @echo off & setlocal enableextensions enabledelayedexpansion
  set par1=%1
  if "%par1%"=="a" (
    set par2=%2
    echo !par2!
    )
  endlocal & goto :EOF
the output will be what one rather would want:
  C:\_D\TEST>cmdfaq a b c d
  b

The latter could, of course, also be written as
  @echo off & setlocal enableextensions disabledelayedexpansion
  set par1=%1
  if not "%par1%"=="a" goto next1
    set par2=%2
    echo %par2%
  :next1
  endlocal & goto :EOF

References/Comments:
 SET /?
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:39 2008
Subject: 159) How do I test that a name does not contain lowercase letters?
Date: Thu,  6 Mar 2008 01:02:39
From: ts@uwasa.fi (Timo Salmi)

Let's limit the lowercase letters to the English alphabet a-z only.

  @echo off & setlocal enableextensions
  set name_=%~1
  if "%name_%"=="" (
    echo Usage: [NameToBeChecked]
    goto :EOF
    )
  ::
  echo %name_%|findstr "[abcdefghijklmnopqrstuvwxyz]"
  if %errorlevel% EQU 0 (
    echo "%name_%" is not uppercase only
    ) else (
    echo "%name_%" is uppercase only)
  endlocal & goto :EOF

There is a catch in using findstr regular expressions. In the above
FINDSTR "[a-z]" would not work as expected from the common regular
expressions definitions. The set option [a-z] seems to case
insensitive in the XP command line interface!
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:40 2008
Subject: 160) How do I get a list of all my folders with and sorted by size?
Date: Thu,  6 Mar 2008 01:02:40
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions enabledelayedexpansion
  ::
  :: Set the auxiliary file names
  set temp_=%temp%
  if defined mytemp set temp_=%mytemp%
  set FolderContent=%temp_%\FullContent.dir
  set SizeAndFolder=%temp_%\SizeAndFolder.dir
  set FolderList=%temp_%\FolderList.dir
  ::
  :: Make the folder list
  dir /s /-c "C:\" > %FolderContent%
  :: Traverse it
  findstr ".Directory.of. .File(s)." %FolderContent%>%SizeAndFolder%
  set Flag=
  for /f "tokens=* delims= " %%a in (
    'type %SizeAndFolder%') do (
      if not defined Flag (
        set Folder=%%a
        set Flag=true
        ) else (
        set Size=                    %%a
        set Flag=
        echo !Size:~-20! !Folder!>>%FolderList%
        )
    )
  ::
  :: Show the result
  sort %FolderList%
  :: Clean up
  :_out
  for %%f in ("%FolderContent%" "%SizeAndFolder%" "%FolderList%") do (
    if exist %%f del %%f
    )
  endlocal & goto :EOF

The output might end with something like
     242904830 bytes Directory of C:\WINDOWS\system32\dllcache
     359978283 bytes Directory of C:\WINDOWS\$NtServicePackUninstall$
     429340336 bytes Directory of C:\WINDOWS\system32
     497131051 bytes Directory of C:\WINDOWS\ServicePackFiles\i386

References/Comments:
 http://www.google.com/groups?selm=3tt2339hipbl4hvg3i5pbqo7v7n7qie3hr%404ax.com
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:41 2008
Subject: 161) How do I test that the Windows Script Host is available?
Date: Thu,  6 Mar 2008 01:02:41
From: ts@uwasa.fi (Timo Salmi)

  @echo off & setlocal enableextensions
  echo Wscript.Echo "@set WSHavailable=1">"%temp%\test$$.vbs"
  cscript /nologo "%temp%\test$$.vbs" > "%temp%\test$$.bat"
  for %%c in (call del) do %%c "%temp%\test$$.bat"
  del "%temp%\test$$.vbs"
  if not "%WSHavailable%"=="1" (echo Windows Script Host is not not available & goto :EOF)
  echo Windows Script Host is available, continuing
  rem Whatever
  endlocal & goto :EOF

References/Comments:
 http://www.google.com/groups?selm=y_j4j.50032%24eY.29616%40newssvr13.news.prodigy.net
--------------------------------------------------------------------

From ts@uwasa.fi Thu Mar  6 01:02:42 2008
Subject: 162) Finding duplicate files in a directory tree
Date: Thu,  6 Mar 2008 01:02:42
From: ts@uwasa.fi (Timo Salmi)

See the responses to this posting
 http://www.google.com/groups?selm=HRG4j.72%24nQ3.42%40newsfe15.phx
in the thread
 http://groups.google.com/group/alt.msdos.batch.nt/browse_frm/thread/1279924b2f59fd4b
--------------------------------------------------------------------
