Hidden features of Windows batch files

WindowsBatch FileHidden Features

Windows Problem Overview


What are some of the lesser know, but important and useful features of Windows batch files?

Guidelines:

  • One feature per answer
  • Give both a short description of the feature and an example, not just a link to documentation
  • Limit answers to native funtionality, i.e., does not require additional software, like the Windows Resource Kit

Clarification: We refer here to scripts that are processed by cmd.exe, which is the default on WinNT variants.

(See also: Windows batch files: .bat vs .cmd?)

Windows Solutions


Solution 1 - Windows

Line continuation:

call C:\WINDOWS\system32\ntbackup.exe ^
    backup ^
    /V:yes ^
    /R:no ^
    /RS:no ^
    /HC:off ^
    /M normal ^
    /L:s ^
    @daily.bks ^
    /F daily.bkf

Solution 2 - Windows

PUSHD path

Takes you to the directory specified by path.

POPD

Takes you back to the directory you "pushed" from.

Solution 3 - Windows

Not sure how useful this would be in a batch file, but it's a very convenient command to use in the command prompt:

C:\some_directory> start .

This will open up Windows Explorer in the "some_directory" folder.

I have found this a great time-saver.

Solution 4 - Windows

I have always found it difficult to read comments that are marked by a keyword on each line:

REM blah blah blah

Easier to read:

:: blah blah blah

Solution 5 - Windows

Variable substrings:

> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456

Solution 6 - Windows

The FOR command! While I hate writing batch files, I'm thankful for it.

FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k

would parse each line in myfile.txt, ignoring lines that begin with a semicolon, passing the 2nd and 3rd token from each line to the for body, with tokens delimited by commas and/or spaces. Notice the for body statements reference %i to get the 2nd token, %j to get the 3rd token, and %k to get all remaining tokens after the 3rd.

You can also use this to iterate over directories, directory contents, etc...

Solution 7 - Windows

Rather than litter a script with REM or :: lines, I do the following at the top of each script:

@echo OFF
goto :START

Description of the script.

Usage:
   myscript -parm1|parm2 > result.txt

:START

Note how you can use the pipe and redirection characters without escaping them.

Solution 8 - Windows

The path (with drive) where the script is : ~dp0

set BAT_HOME=%~dp0
echo %BAT_HOME%
cd %BAT_HOME%

Solution 9 - Windows

The %~dp0 piece was mentioned already, but there is actually more to it: the character(s) after the ~ define the information that is extracted.
No letter result in the return of the patch file name
d - returns the drive letter
p - returns the path
s - returns the short path
x - returns the file extension
So if you execute the script test.bat below from the c:\Temp\long dir name\ folder,

@echo off
echo %0
echo %~d0
echo %~p0
echo %~dp0
echo %~x0
echo %~s0
echo %~sp0

you get the following output

> test > c: > \Temp\long dir name
> c:\Temp\long dir name
> .bat > c:\Temp\LONGDI1\test.bat > \Temp\LONGDI1\

And if a parameter is passed into your script as in
test c:\temp\mysrc\test.cpp
the same manipulations can be done with the %1 variable.

But the result of the expansion of %0 depends on the location!
At the "top level" of the batch it expands to the current batch filename.
In a function (call), it expands to the function name.

@echo off
echo %0
call :test
goto :eof

:test
echo %0
echo %~0
echo %~n0

The output is (the batchfile is started with myBatch.bat )

myBatch.bat
:test
:test
myBatch

Solution 10 - Windows

By using CALL, EXIT /B, SETLOCAL & ENDLOCAL you can implement subroutines with local variables.

example:

@echo off

set x=xxxxx
call :sub 10
echo %x%
exit /b

:sub
setlocal
set /a x=%1 + 1
echo %x%
endlocal
exit /b

This will print

11
xxxxx

even though :sub modifies x.

Solution 11 - Windows

Sneaky trick to wait N seconds (not part of cmd.exe but isn't extra software since it comes with Windows), see the ping line. You need N+1 pings since the first ping goes out without a delay.

    echo %time%
    call :waitfor 5
    echo %time%
    goto :eof
:waitfor
    setlocal
    set /a "t = %1 + 1"
    >nul ping 127.0.0.1 -n %t%
    endlocal
    goto :eof

Solution 12 - Windows

Escaping the "plumbing":

echo ^| ^< ^> ^& ^\ ^^

Solution 13 - Windows

Being able to run commands and process the output (like backticks of '$()' in bash).

for /f %i in ('dir /on /b *.jpg') do echo --^> %i

If there are spaces in filenames, use this:

for /f "tokens=*" %i in ('dir /on /b *.jpg') do echo --^> %i

Solution 14 - Windows

Creating an empty file:

> copy nul filename.ext

Solution 15 - Windows

To hide all output from a command redirect to >nul 2>&1.

For example, the some command line programs display output even if you redirect to >nul. But, if you redirect the output like the line below, all the output will be suppressed.

PSKILL NOTEPAD >nul 2>&1

EDIT: See Ignoring the output of a command for an explanation of how this works.

Solution 16 - Windows

PAUSE

Stops execution and displays the following prompt:

Press any key to continue . . .

Useful if you want to run a batch by double-clicking it in Windows Explorer and want to actually see the output rather than just a flash of the command window.

Solution 17 - Windows

The equivalent of the bash (and other shells)

echo -n Hello # or
echo Hello\\c

which outputs "Hello" without a trailing newline. A cmd hack to do this:

<nul set /p any-variable-name=Hello

set /p is a way to prompt the user for input. It emits the given string and then waits, (on the same line, i.e., no CRLF), for the user to type a response.

<nul simply pipes an empty response to the set /p command, so the net result is the emitted prompt string. (The variable used remains unchanged due to the empty reponse.)

Problems are: It's not possible to output a leading equal sign, and on Vista leading whitespace characters are removed, but not on XP.

Solution 18 - Windows

Search and replace when setting environment variables:

> @set fname=%date:/=%

...removes the "/" from a date for use in timestamped file names.

and substrings too...

> @set dayofweek=%fname:~0,3%

Solution 19 - Windows

Integer arithmetic:

> SET /A result=10/3 + 1
4

Solution 20 - Windows

Command separators:

cls & dir
copy a b && echo Success
copy a b || echo Failure

At the 2nd line, the command after && only runs if the first command is successful.

At the 3rd line, the command after || only runs if the first command failed.

Solution 21 - Windows

Output a blank line:

echo.

Solution 22 - Windows

You can chain if statements to get an effect like a short-circuiting boolean `and'.

if foo if bar baz

Solution 23 - Windows

To quickly convert an Unicode text file (16bit/char) to a ASCII DOS file (8bit/char).

C:\> type unicodeencoded.txt > dosencoded.txt

as a bonus, if possible, characters are correctly mapped.

Solution 24 - Windows

if block structure:

if "%VS90COMNTOOLS%"=="" (
  echo: Visual Studio 2008 is not installed
  exit /b
)

Solution 25 - Windows

Delayed expansion of variables (with substrings thrown in for good measure):

    @echo off
    setlocal enableextensions enabledelayedexpansion
    set full=/u01/users/pax
:loop1
    if not "!full:~-1!" == "/" (
        set full2=!full:~-1!!full2!
        set full=!full:~,-1!
        goto :loop1
    )
    echo !full!
    endlocal

Solution 26 - Windows

Doesn't provide much functionality, but you can use the title command for a couple of uses, like providing status on a long script in the task bar, or just to enhance user feedback.

@title Searching for ...
:: processing search
@title preparing search results
:: data processing

Solution 27 - Windows

example of string subtraction on date and time to get file named "YYYY-MM-DD HH:MM:SS.txt"

> echo test > "%date:~0,4%-%date:~5,2%-%date:~8,2% %time:~0,2%_%time:~3,2%_%time:~6,2%.txt"

I use color to indicate if my script end up successfully, failed, or need some input by changing color of text and background. It really helps when you have some machine in reach of your view but quite far away

> color XY

where X and Y is hex value from 0 to F, where X - background, Y - text, when X = Y color will not change.

> color Z

changes text color to 'Z' and sets black background, 'color 0' won't work

for names of colors call

>color ?

Solution 28 - Windows

Don't have an editor handy and need to create a batch file?

copy con test.bat

Just type away the commands, press enter for a new line. Press Ctrl-Z and Enter to close the file.

Solution 29 - Windows

Total control over output with spacing and escape characters.:

echo.    ^<resourceDir^>/%basedir%/resources^</resourceDir^>

Solution 30 - Windows

TheSoftwareJedi already mentioned the for command, but I'm going to mention it again as it is very powerful.

The following outputs the current date in the format YYYYMMDD, I use this when generating directories for backups.

for /f "tokens=2-4 delims=/- " %a in ('DATE/T') do echo %c%b%a

Solution 31 - Windows

You can use call to evaluate names later, leading to some useful properties.

call set SomeEnvVariable_%extension%=%%%somevalue%%%

Using call to set variables whose names depend on other variables. If used with some variable naming rules, you can emulate data collections like arrays or dictionaries by using careful naming rules. The triple %'s around somevalue are so it will evaluate to one variable name surrounded by single %'s after the call and before set is invoked. This means two %'s in a row escape down to a single % character, and then it will expand it again, so somevalue is effectively a name pointer.

call set TempVar=%%SomeEnvVariable_%extension%%%

Using it with a temp variable to retrieve the value, which you can then use in logic. This most useful when used in conjunction with delayed variable expansion.

To use this method properly, delayed variable expansion needs to be enabled. Because it is off by default, it is best to enable it within the script by putting this as one of the first instructions:

setlocal EnableDelayedExpansion

Solution 32 - Windows

Searching for an executable on the path (or other path-like string if necessary):

c:\> for %i in (cmd.exe) do @echo. %~$PATH:i
C:\WINDOWS\system32\cmd.exe

c:\> for %i in (python.exe) do @echo. %~$PATH:i
C:\Python25\python.exe

c:\>

Solution 33 - Windows

With regard to using :: instead of REM for comments: be careful! :: is a special case of a CALL label that acts like a comment. When used inside brackets, for instance in a FOR or IF loop, the function will prematurely exit. Very frustrating to debug!

See http://www.ss64.com/nt/rem.html for a full description.

(adding as a new answer instead of a comment to the first mention of this above because I'm not worthy of commeting yet :0)

Solution 34 - Windows

A lot of people use GOTO :EOF these days to terminate their batch files, but you can also use EXIT /B for this purpose.

The advantage behind using EXIT /B is that you can add an errorlevel after EXIT /B, and it will exit with that errorlevel.

Solution 35 - Windows

Local variables are still parsed for the line that ENDLOCAL uses. This allows for tricks like:

ENDLOCAL & SET MYGLOBAL=%SOMELOCAL% & SET MYOTHERGLOBAL=%SOMEOTHERLOCAL%

This is is a useful way to transmit results to the calling context. Specifically, %SOMELOCAL% goes out of scope as soon as ENDLOCAL completes, but by then %SOMELOCAL% is already expanded, so the MYGLOBAL is assigned in the calling context with the local variable.

For the same reason, if you decide to do:

ENDLOCAL & SET MYLOCAL=%MYLOCAL%

You'll discover your new MYLOCAL variable is actually now around as a regular environment variable instead of the localized variable you may have intended it to be.

Solution 36 - Windows

Subroutines (outputs 42):

    @echo off
    call :answer 42
    goto :eof
:do_something
    echo %1
    goto :eof

and subroutines returning a value (outputs 0, 1, 2, and so on):

    @echo off
    setlocal enableextensions enabledelayedexpansion
    call :seq_init seq1
:loop1
    if not %seq1%== 10 (
        call :seq_next seq1
        echo !seq1!
        goto :loop1
    )
    endlocal
    goto :eof

:seq_init
    set /a "%1 = -1"
    goto :eof
:seq_next
    set /a "seq_next_tmp1 = %1"
    set /a "%1 = %seq_next_tmp1% + 1"
    set seq_next_tmp1=
    goto :eof

Solution 37 - Windows

Quick edit mode in cmd.exe is my favorite. This is slightly off topic, but when interacting with the command shell it can be a lifesaver. No, I'm not being hyperbolic--you will only see caret-capitol-v a certain number of times before you die; the more you see, the faster you die.

  1. Open up regedit (caution, not my fault, blue screen, etc)
  2. Go to HKCU/Console
  3. Set QuickEdit to 1

(You can set this from the UI as well, which is probably the better way. See the comments for instructions. Also there's a nice one line script to do this as well.)

Now, to copy, just left-click and drag to select and right click to copy. To paste, just right click.

NO MORE ^V^V^V^V^V^V^V^V^V^V^V^V^V^V!!!

Crap, I think I just killed somebody. Sorry!

Solution 38 - Windows

Call Set - Expands Environment variables several levels deep.

Found this at http://ss64.com/nt/call.html#advanced from answer to another SO question Batch file variables initialized in a for loop

set VarName=Param
set Param=This

call set Answer=%%%Varname%%%
Echo %Answer%

gives

set VarName=Param
set Param=This
call set Answer=%Param%
Echo This
This

Solution 39 - Windows

The subdirectory option on 'remove directory':

rd /s /q junk

Solution 40 - Windows

SHIFT

It's a way to iterate through a variable number of arguments passed into a script (or sub-routine) on the command line. In its simplest usage, it shifts %2 to be %1, %3 to be %2, and so-on. (You can also pass in a parameter to SHIFT to skip multiple arguments.) This makes the command "destructive" (i.e. %1 goes away forever), but it allows you to avoid hard-coding a maximum number of supported arguments.

Here's a short example to process command-line arguments one at a time:

:ParseArgs

if "%1"=="" (
    goto :DoneParsingArgs
)

rem ... do something with %1 ...

shift

goto :ParseArgs


:DoneParsingArgs

rem ...

Solution 41 - Windows

Redirecting output to the console, even if the batch's output is already redirected to a file via the > con syntax.

Example: foo.cmd:

echo a
echo b > con

Calling:

foo.cmd > output.txt

This will result in "a" going to output.txt yet "b" going to the console.

Solution 42 - Windows

You can use errorlevel to check if a given program is available on the system (current dir or path) where your batchfile will run. For this to work the program you are testing for must run, exit and set an exit code when it does. In the example I use -? as an arg to myExe, most CLI programs have a similar arg such as -h, --help, -v etc ... this ensures it simply runs and exits leaving or setting errorlevel 0

myExe -? >nul 2>&1 
Set errCode=%errorlevel%
@if %errCode% EQU 0 (
	echo myExe -? does not return an error (exists)
) ELSE (
	echo myExe -? returns an error (does not exist)
)

Yes, you could test errorlevel directly rather than assigning it to errCode but this way you can have commands between the test and the condition and you test the condition repeatedly as needed.

Solution 43 - Windows

the correct format for loops with numeric variables is

for /l %%i in (startNumber, counter, endNumber) do echo %%i

more details > http://www.ss64.com/nt/for.html

Solution 44 - Windows

For parsing stdin from inside a script you need that trick with the FOR and FIND commands:

for /f "tokens=*" %%g in ('find /V ""') do (
     :: do what you want with %%g
     echo %%g
)

Solution 45 - Windows

The CHOICE command prompts the user for one of multiple options (via a single keypress)

@echo off
echo Please choose one of the following options
echo 1. Apple
echo 2. Orange
echo 3. Pizza
echo a, b, c. Something else
choice /c:123abc /m "Answer?"
set ChoiceLevel=%ErrorLevel%
echo Choice was: %ChoiceLevel%

%ChoiceLevel% will be the nth option selected (in the above example, b=5).

More details at the CHOICE reference page on SS64.com.

Solution 46 - Windows

A handy trick when you want to copy files between branches:

C:\src\branch1\mydir\mydir2\mydir3\mydir4>xcopy %cd:branch1=branch2%\foo*
Overwrite C:\src\branch1\mydir\mydir2\mydir3\mydir4\foo.txt (Yes/No/All)? y
C:\src\branch2\mydir\mydir2\mydir3\mydir4\foo.txt

This uses both the %cd% environment variable, and environment variable substitution.

Solution 47 - Windows

Get the current day, month and year (locale-independently):

for /f "tokens=1-4 delims=/-. " %%i in ('date /t') do (call :set_date %%i %%j %%k %%l)
goto :end_set_date

:set_date
if ("%1:~0,1%" gtr "9") shift
for /f "skip=1 tokens=2-4 delims=(-)" %%m in ('echo,^|date') do (set %%m=%1&set %%n=%2&set %%o=%3)
goto :eof

:end_set_date

echo day in 'DD' format is %dd%; month in 'MM' format is %mm%; year in 'YYYY' format is %yy%

Solution 48 - Windows

I find the ease with which you can redirect the output of commands to files extremely useful:

DIR *.txt > tmp.txt
DIR *.exe >> tmp.txt

Single arrow creates, or overwrites the file, double arrow appends to it. Now I can open tmp.txt in my text editor and do all kinds of good stuff.

Solution 49 - Windows

/c param for the cmd.exe itself, tells it to run and then do these commands.

I used to find myself frequently doing:

win+r, cmd RETURN, ping google.com RETURN

but now I just do:

win+r, cmd /c ping google.com RETURN

much faster. also helpful if you're using pstools and you want to use psexec to do some command line function on the remote machine.

EDIT: /k Works the same, but leaves the prompt open. This might come in handy more often.

Solution 50 - Windows

Inline comments using &::.

:: This is my batch file which does stuff.
copy thisstuff thatstuff  &:: We need to make a backup in case we screw up!

:: ... do lots of other stuff

How does this work? It's an ugly hack. The & is the command separator roughly approximating the ; of UNIX shells. The :: is another ugly hack that kinda-sorta emulates a REM statement. The end result is that you execute your command and then you execute a do-nothing command, thus approximating a comment.

This doesn't work in all situations, but it works often enough to be a useful hack.

Solution 51 - Windows

For what it's worth, this is quite a good online reference for Windows CMD or batch files. I learned a few things I didn't know from it.

Solution 52 - Windows

[forfiles][1] is very useful, for instance, to recursive delete all files older than two days

forfiles /D -2 /P "C:\Temp" /S /C "cmd /c del @path"

[1]: http://technet.microsoft.com/nl-nl/library/cc753551%28WS.10%29.aspx "forfiles"

Solution 53 - Windows

Findstr with regular expression support:

findstr "^[0-9].*" c:\windows\system32\drivers\etc\hosts

Solution 54 - Windows

Using pushd to a UNC path will create a temporary drive mapping (starting with Z and working backward to find the next available letter) and put you in that drive and path. When you popd or exit the command prompt, the temporary mapping is gone.

   C:\>pushd \\yourmom\jukebox

   Z:\>pushd \\yourmom\business

   Y:\>

Also, not so much a batch tip as a command-line environment tip, but when you're working at the commandline with pushd and popd and network shares, it's useful to modify your prompt with the $+ (show pushd stack depth) and $M (show network share path).

   C:\utils>prompt $+$m$p$g

   C:\utils>pushd m:

   +\\yourmom\pub M:\>pushd c:\

   ++c:\>pushd
   M:\
   C:\utils  

   ++c:\>popd

   +\\yourmom\pub M:\>popd

   C:\utils>

Solution 55 - Windows

Find strings in files in a folder using the pipe '|' command:

dir /b *.* | findstr /f:/ "thepattern"

Solution 56 - Windows

Arrays in batch-files.

Set a value:

set count=1
set var%count%=42

Extract a value at the command-line:

call echo %var%count%%

Extract a value in a batch-file:

call echo %%var%count%%%

Note the extra strafing % signs.

The technique may look a little hairy, but it's quite useful. The above will print the contents of var1 (i.e. 42) as we explained. We could also replace the echo command with a set if we wanted to set some other variable to the value in var1. Meaning the following is a valid assignment at the command line:

call set x=%var%count%%

Then to see the value of va1:

echo %x%

Solution 57 - Windows

Doskey Macros.

I've long lost the reference for this, but I still think it's a good idea, and worth sharing.

We can merge batch-files and doskey scripts into a single file. This might seem a little overly clever, but it works.

;= @echo off
;= rem Call DOSKEY and use this file as the macrofile
;= %SystemRoot%\system32\doskey /listsize=1000 /macrofile=%0%
;= rem In batch mode, jump to the end of the file
;= goto end

;= Doskey aliases
h=doskey /history

;= File listing enhancements
ls=dir /x $*

;= Directory navigation
up=cd ..
pd=pushd

;= :end
;= rem ******************************************************************
;= rem * EOF - Don't remove the following line.  It clears out the ';' 
;= rem * macro. Were using it because there is no support for comments
;= rem * in a DOSKEY macro file.
;= rem ******************************************************************
;=

It works by defining a fake doskey macro ';' which is gracefully (or silently) ignored when it is interpreted as a batch-file.

I've shortened the version listed here, if you want more, go here.

Solution 58 - Windows

Here how to build a CLASSPATH by scanning a given directory.

setlocal ENABLEDELAYEDEXPANSION
if defined CLASSPATH (set CLASSPATH=%CLASSPATH%;.) else (set CLASSPATH=.)
FOR /R .\lib %%G IN (*.jar) DO set CLASSPATH=!CLASSPATH!;%%G
Echo The Classpath definition is %CLASSPATH%

works in XP (or better). With W2K, you need to use a couple of BAT files to achieve the same result (see Include all jars in the classpath definition ).

It's not needed for 1.6 since you can specify a wildcard directly in CLASSPATH (ex. -cp ".\lib*").

Solution 59 - Windows

Multiple commands in one line, useful in many situations:

& Used to combine two commands, executes command1 and then command2 && A conditional combination, executes command2 if command1 completes successfully ¦¦ Command2 executes only if command1 does not complete successfully.

Examples:

:: ** Edit the most recent .TXT file and exit, useful in a .CMD / .BAT **
FOR /F %%I IN ('DIR *.TXT /B /O:-N') DO NOTEPAD %%I & EXIT


:: ** If exist any .TXT file, display the list in NOTEPAD, if not it 
:: ** exits without any error (note the && and the 2> error redirection)
DIR *.TXT > TXT.LST 2> NUL && NOTEPAD TXT.LST

Solution 60 - Windows

Allows you to change directory based on environment variable without having to specify the '%' directive. If the variable specified does not exist then try the directory name.

@if defined %1 (call cd "%%%1%%") else (call cd %1)

Solution 61 - Windows

I would say DEBUG.EXE is a VERY useful and VERY underused feature of batch files.

The DEBUG command allows you to...

  1. Assemble and disassemble 16-bit code
  2. Read/write memory (Modern protected memory makes this considerably less useful.)
  3. Read data sectors from the hard drive, raw
  4. Hex edit

In short, this tool is EXTREMELY powerful. It might not be used much these days anymore, but the power to call up and control this functionality from a batch script adds a staggering amount of power to batch scripting.

NOTE: Microsoft has removed this command from 64 bit editions of Windows Xp and Vista and intends to remove it from Windows 7 altogether, from what I've heard.

Solution 62 - Windows

Setting environment variables from a file with SET /P

SET /P SVNVERSION=<ver.tmp

Solution 63 - Windows

A method to set the errorlevel to any number you desire:

CMD /C EXIT number

Solution 64 - Windows

The goto :eof pasteboard

I add "goto :eof" to end of my scripts as a handy space for code fragments. That way I can quickly copy/paste to and from this area, without having to comment/uncomment.

goto :eof
:: code scraps
call this.bat
call that.bat
set TS=%DATE:~10%%DATE:~4,2%%DATE:~7,2%-%TIME:~0,2%%TIME:~3,2%%TIME:~6%%
for /R C:\temp\ %%G in (*.bak) DO del %%G

Solution 65 - Windows

Hide input for an interactive batch script:

  @echo off

  echo hP1X500P[PZBBBfh#b##fXf-V@`$fPf]f3/f1/5++u5>in.com

  set /p secret_password="Enter password:"<nul

  for /f "tokens=*" %%i in ('in.com') do (set secret_password=%%i)

  del in.com

Solution 66 - Windows

List all drives:

fsutil fsinfo drives

Solution 67 - Windows

Create and start editing a new file

copy con new.txt
This is the contents of my file
^Z

Ctrl+Z sends the ASCII EOF character. This is like heredocs in bash:

cat <<EOF > new.txt
This is the contents of my file
EOF

Solution 68 - Windows

Remove surrounding quote.

for /f "useback tokens=*" %%a in ('%str%') do set str=%%~a

I recently have to write a batch file that is called by VS prebuild event and I want to pass in the project directory as parameter. In the batch file I need to concatenate the path with nested subfolder name, but first the surrounding quote need to be removed.

Solution 69 - Windows

Bail on error.

IF "%errorlevel%" NEQ "0" (
   echo "ERROR:  Something broke.  Bailing out."
   exit /B 1
)

Solution 70 - Windows

Symbolic links:

mklink /d directorylink ..\realdirectory
mklink filelink realfile

The command is native on Windows Server 2008 and newer, including Vista and Windows 7. (It is also included in some Windows Resource Kits.)

Solution 71 - Windows

Append files using copy:

copy file1.txt+file2.txt+file3.txt append.txt

Also, to set all CLI parameters to a single variable:

SET MSG=%*

This will take every word (or symbol) that is separated by spaces and save it to a single batch file variable. Technically, each parameter is %1, %2, $3, etc., but this SET command uses a wildcard to reference every parameter in stdin.

Batch File:

@SET MSG=%*
@echo %MSG%

Command Line:

C:\test>test.bat Hello World!
Hello World!

Solution 72 - Windows

Recursively search for a string in a directory tree:

findstr /S /C:"string literal" *.*

You can also use regular expressions:

findstr /S /R "^ERROR" *.log

Recursive file search:

dir /S myfile.txt

Solution 73 - Windows

Much like above, using CALL, EXIT /B, SETLOCAL & ENDLOCAL you can implement functions with local variables and return values.

example:

@echo off

set x=xxxxx
call :fun 10
echo "%x%"
echo "%y%"
exit /b

:fun
setlocal
set /a y=%1 + 1
endlocal & set x=%y%
exit /b

This will print:

"11"
""

The y variable never leaves the local scope, but because of the way CMD resolves a single line at a time, you can extract the value into the x variable in the parent scope.

Solution 74 - Windows

For loops with numeric counters (outputs 1 through 10):

for /l %i in (1,1,10) do echo %i

Solution 75 - Windows

here's one trick that I use to run My Nant Build script consecutively without having to click the batch file over and over again.

:CODELINE
NANT.EXE -buildfile:alltargets.build -l:build.log build.product
@pause
GOTO :CODELINE

What will happen is that after your solution finished building, it will be paused. And then if you press any key it will rerun the build script again. Very handy I must say.

Solution 76 - Windows

HELP

When working with different OS version it's important to know what commands are available natively. Typing HELP at the command prompt shows what commands are available, with a brief description of what they do.

cmd.exe /? 

This will list all the command line parameters for launching a command prompt as well as registry tweaks that change system wide behavior.

Solution 77 - Windows

When using command extensions shell options in a script, it is HIGHLY suggested that you do the following trick at the beginning of your scripts.

-- Information pasted from [http://www.ss64.com/nt/setlocal.html][1]

>SETLOCAL will set an ERRORLEVEL if given an argument. It will be zero if one of the two valid arguments is given and one otherwise.

>You can use this in a batch file to determine if command extensions are available, using the following technique:

VERIFY errors 2>nul
SETLOCAL ENABLEEXTENSIONS
IF ERRORLEVEL 1 echo Unable to enable extensions

>This works because "VERIFY errors" sets ERRORLEVEL to 1 and then the SETLOCAL will fail to reset the ERRORLEVEL value if extensions are not available (e.g. if the script is running under command.com)

>If Command Extensions are permanently disabled then SETLOCAL ENABLEEXTENSIONS will not restore them.

[1]: http://www.ss64.com/nt/setlocal.html "http://www.ss64.com/nt/setlocal.html"

Solution 78 - Windows

A very old (ca 1990) trick to get the total size of the environment variables:

set > test
dir test
del test

Solution 79 - Windows

This batch file works both with simple files as well as directories as command line parameters (you can mix them in any order). The loop runs the command ('echo' in this example) on any specified file, if a parameter is a directory it runs the command recursively on each file in it.

@echo off
for /f "delims=" %%f in ('dir %* /a-d /b /s') do echo %%f

Solution 80 - Windows

The IF command! Without it my batch file was junk!

@echo off
IF exist %windir%\system32\iexplore.exe goto end

echo Hmm... it seems you do not have Internet Explorer.
echo Great! You seem to understand ;)

:end
echo Hmm... You have Internet Explorer.
echo That is bad :)

Solution 81 - Windows

I really like this Windows XP Commands reference, as well as the Syntax link at the top; it covers many of the tips and tricks already found in other answers.

Solution 82 - Windows

There is also the EDLIN command. While it may be an old bastard tool once used for line-based text editing, the fact that it's controllable from the command line makes it rather useful for batch scripting, mostly because, just like any other case you'd be using EDLIN, it's the only tool available. After all, EDLIN is not a tool you would ordinarily want to use for text editing, unless you are somewhat masochistic. To quote Tim Patterson (the fellow who wrote it): "I was aghast when I heard that IBM was using it and not throwing it out the window."

NOTE: EDLIN adds old-fashioned EOF (1A) markers to files it edits. If you need to remove them, you'll probably have to use DEBUG.

Solution 83 - Windows

When passing an unknown number of parameters to a batch file, e.g. when several files are dragged and dropped onto the batch file to launch it, you could refer to each parameter variable by name, e.g.

TYPE %1
TYPE %2
TYPE %3
TYPE %4
TYPE %5
...etc

but this gets very messy when you want to check if each parameter exists:

if [%1] NEQ [] (
TYPE %1
)
if [%2] NEQ [] (
TYPE %2
)
if [%3] NEQ [] (
TYPE %3
)
if [%4] NEQ [] (
TYPE %4
)
if [%5] NEQ [] (
TYPE %5
)
...etc

Also, you can only accept a limited number of parameters with this approach.

Instead, try using the SHIFT command:

:loop
IF [%1] NEQ [] (
TYPE %1
) ELSE (
GOTO end
)
SHIFT
GOTO loop
:end

SHIFT will move all the parameters down by one, so %2 becomes %1 and %3 becomes %2 etc.

Solution 84 - Windows

FIND as a replacement for grep.
I hacked a little "phonebook" for myself with find. Very usefull:

@echo off
:begin
set /p term=Enter query: 
type phonebookfile.txt |find /i "%term%"
if %errorlevel% == 0 GOTO :choose
echo No entry found
set /p new_entry=Add new entry: 
echo %new_entry% >> phonebookfile.txt 
:choose
set /p action=(q)uit, (n)ew query or (e)dit? [q] 
if "%action%"=="n" GOTO anfang
if "%action%"=="e" (
	notepad phonebookfile.txt
	goto :choose
)

Very fast and effective.

Solution 85 - Windows

Line-based execution

While not a clear benefit in most cases, it can help when trying to update things while they are running. For example:

UpdateSource.bat

copy UpdateSource.bat Current.bat
echo "Hi!"

Current.bat

copy UpdateSource.bat Current.bat

Now, executing Current.bat produces this output.

HI!

Watch out though, the batch execution proceeds by line number. An update like this could end up skipping or moving back a line if the essential lines don't have exactly the same line numbers.

Solution 86 - Windows

I use them as quick shortcuts to commonly used directories. An example file named "sandbox.bat" which lives in a directory in my PATH

EXPLORER "C:\Documents and Settings\myusername\Desktop\sandbox"

Invoking the script is just WIN+R --> sandbox

Solution 87 - Windows

To get the current date / time to use for log files, etc., I use this in my batch files:

for /f "usebackq tokens=1,2,3,4,5,6,7 delims=/:. " %%a in (`echo %DATE% %TIME%`) do set NOW=%%d%%b%%c_%%e%%f%%g
set LOG=output_%NOW%.log

Solution 88 - Windows

You can modify a batch file while it is running. For example you can add a forgotten pause to the end of the file while it's running if you wanted to see the results before the batch file quit.

see https://stackoverflow.com/questions/906586/changing-a-batch-file-when-its-running

I personally think of this more as a gotcha than a feature.

Solution 89 - Windows

To set an enivroment variable from the first line of a file, I use this:

rem a.txt contains one line: abc123
set /p DATA=<a.txt
echo data: %DATA%

This will output: abc123

Solution 90 - Windows

One of the most common requirements of batch scripting is to log the output generated for later review. Yes, you can redirect the stdout and stderr to a file but then you can't see what is going on unless you tail the log file.

So consider running your batch scripts using a stdout/stderr logging utility like logger which will log the output with a timestamp and you are still able to see the script progress as it happens.

Yet another stdout/stderr logging utility

Yet another stdout/stderr logging utility [2010-08-05]
Copyright (C) 2010 LoRd_MuldeR <[email protected]>
Released under the terms of the GNU General Public License (see License.txt)

Usage:
  logger.exe [logger options] : program.exe [program arguments]
  program.exe [program arguments] | logger.exe [logger options] : -

Options:
  -log <file name>  Name of the log file to create (default: "<program> <time>.log")
  -append           Append to the log file instead of replacing the existing file
  -mode <mode>      Write 'stdout' or 'stderr' or 'both' to log file (default: 'both')
  -format <format>  Format of log file, 'raw' or 'time' or 'full' (default: 'time')
  -filter <filter>  Don't write lines to log file that contain this string
  -invert           Invert filter, i.e. write only lines to log file that match filter
  -ignorecase       Apply filter in a case-insensitive way (default: case-sensitive)
  -nojobctrl        Don't add child process to job object (applies to Win2k and later)
  -noescape         Don't escape double quotes when forwarding command-line arguments
  -silent           Don't print additional information to the console
  -priority <flag>  Change process priority (idle/belownormal/normal/abovenormal/high)
  -inputcp <cpid>   Use the specified codepage for input processing (default: 'utf8')
  -outputcp <cpid>  Use the specified codepage for log file output (default: 'utf8')

Solution 91 - Windows

Extract random lines of text

@echo off

:: Get time (alas, it's only HH:MM xM

for /f %%a in ('time /t') do set zD1=%%a



:: Get last digit of MM

set zD2=%zD1:~4,1%



:: Seed the randomizer, if needed

if not defined zNUM1 set /a zNUM1=%zD2%


:: Get a kinda random number

set /a zNUM1=zNUM1 * 214013 + 2531011

set /a zNUM2=zNUM1 ^>^> 16 ^& 0x7fff


:: Pull off the first digit

:: (Last digit would be better, but it's late, and I'm tired)

set zIDX=%zNUM2:~0,1%


:: Map it down to 0-3

set /a zIDX=zIDX/3


:: Finally, we can set do some proper initialization

set /a zIIDX=0

set zLO=

set zLL=""


:: Step through each line in the file, looking for line zIDX

for /f "delims=@" %%a in (c:\lines.txt) do call :zoo  %zIDX%  %%a


:: If line zIDX wasn't found, we'll settle for zee LastLine

if "%zLO%"=="" set zLO=%zLL%

goto awdun


:: See if the current line is line zIDX

:zoo


:: Save string of all parms

set zALL=%*


:: Strip off the first parm (sure hope lines aren't longer than 254 chars)

set zWORDS=%zALL:~2,255%


:: Make this line zee LastLine

set zLL=%zWORDS%


:: If this is the line we're looking for, make it zee LineOut

if {%1}=={%zIIDX%} set zLO=%zWORDS%


:: Keep track of line numbers

set /a zIIDX=%zIIDX% + 1

goto :eof




:awdun

echo ==%zLO%==


:: Be socially responsible

set zALL=

set zD1=

set zD2=

set zIDX=

set zIIDX=

set zLL=

set zLO=

:: But don't mess with seed

::set zNUM1=

set zNUM2=

set zWORDS=

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionChris NoeView Question on Stackoverflow
Solution 1 - WindowsChris NoeView Answer on Stackoverflow
Solution 2 - WindowsravenView Answer on Stackoverflow
Solution 3 - WindowsLeopardSkinPillBoxHatView Answer on Stackoverflow
Solution 4 - WindowsChris NoeView Answer on Stackoverflow
Solution 5 - WindowsChris NoeView Answer on Stackoverflow
Solution 6 - WindowsTheSoftwareJediView Answer on Stackoverflow
Solution 7 - WindowsPatrick CuffView Answer on Stackoverflow
Solution 8 - WindowsRealHowToView Answer on Stackoverflow
Solution 9 - WindowsHartmutView Answer on Stackoverflow
Solution 10 - WindowsFerruccioView Answer on Stackoverflow
Solution 11 - WindowspaxdiabloView Answer on Stackoverflow
Solution 12 - WindowsChris NoeView Answer on Stackoverflow
Solution 13 - WindowspaxdiabloView Answer on Stackoverflow
Solution 14 - WindowsrbraybView Answer on Stackoverflow
Solution 15 - WindowsaphoriaView Answer on Stackoverflow
Solution 16 - WindowsravenView Answer on Stackoverflow
Solution 17 - WindowspaxdiabloView Answer on Stackoverflow
Solution 18 - WindowsSqlACIDView Answer on Stackoverflow
Solution 19 - WindowsChris NoeView Answer on Stackoverflow
Solution 20 - WindowsdoekmanView Answer on Stackoverflow
Solution 21 - WindowspaxdiabloView Answer on Stackoverflow
Solution 22 - WindowsJackView Answer on Stackoverflow
Solution 23 - WindowsRealHowToView Answer on Stackoverflow
Solution 24 - WindowsFerruccioView Answer on Stackoverflow
Solution 25 - WindowspaxdiabloView Answer on Stackoverflow
Solution 26 - WindowsHartmutView Answer on Stackoverflow
Solution 27 - WindowsMoreThanChaosView Answer on Stackoverflow
Solution 28 - WindowsHartmutView Answer on Stackoverflow
Solution 29 - WindowspaxdiabloView Answer on Stackoverflow
Solution 30 - WindowsremonedoView Answer on Stackoverflow
Solution 31 - WindowsLara DouganView Answer on Stackoverflow
Solution 32 - WindowspaxdiabloView Answer on Stackoverflow
Solution 33 - Windowsmatt wilkieView Answer on Stackoverflow
Solution 34 - WindowsCoding With StyleView Answer on Stackoverflow
Solution 35 - WindowsCoding With StyleView Answer on Stackoverflow
Solution 36 - WindowspaxdiabloView Answer on Stackoverflow
Solution 37 - Windowsuser1228View Answer on Stackoverflow
Solution 38 - WindowsAndy MorrisView Answer on Stackoverflow
Solution 39 - WindowspaxdiabloView Answer on Stackoverflow
Solution 40 - WindowsreubenView Answer on Stackoverflow
Solution 41 - WindowsNicJView Answer on Stackoverflow
Solution 42 - Windowsbatch foolView Answer on Stackoverflow
Solution 43 - WindowsAlin SfetcuView Answer on Stackoverflow
Solution 44 - WindowsPhilibert PerusseView Answer on Stackoverflow
Solution 45 - WindowsNicJView Answer on Stackoverflow
Solution 46 - WindowsIgor DvorkinView Answer on Stackoverflow
Solution 47 - WindowsAndrei CoșcodanView Answer on Stackoverflow
Solution 48 - WindowsravenView Answer on Stackoverflow
Solution 49 - WindowsDean RatherView Answer on Stackoverflow
Solution 50 - WindowsJUST MY correct OPINIONView Answer on Stackoverflow
Solution 51 - WindowsConcernedOfTunbridgeWellsView Answer on Stackoverflow
Solution 52 - WindowsBrecht YpermanView Answer on Stackoverflow
Solution 53 - WindowsBartekBView Answer on Stackoverflow
Solution 54 - WindowsthatbrentguyView Answer on Stackoverflow
Solution 55 - WindowsFrans BoumaView Answer on Stackoverflow
Solution 56 - WindowsBen BurnettView Answer on Stackoverflow
Solution 57 - WindowsBen BurnettView Answer on Stackoverflow
Solution 58 - WindowsRealHowToView Answer on Stackoverflow
Solution 59 - WindowsPabloGView Answer on Stackoverflow
Solution 60 - WindowsPaul HobbsView Answer on Stackoverflow
Solution 61 - WindowsCoding With StyleView Answer on Stackoverflow
Solution 62 - WindowsAnton TykhyyView Answer on Stackoverflow
Solution 63 - WindowsCoding With StyleView Answer on Stackoverflow
Solution 64 - WindowsChris NoeView Answer on Stackoverflow
Solution 65 - WindowsAndrei CoșcodanView Answer on Stackoverflow
Solution 66 - WindowsAndrei CoșcodanView Answer on Stackoverflow
Solution 67 - Windowsdave1010View Answer on Stackoverflow
Solution 68 - WindowsFadrian SudamanView Answer on Stackoverflow
Solution 69 - WindowscaseyboardmanView Answer on Stackoverflow
Solution 70 - WindowsSoulmanView Answer on Stackoverflow
Solution 71 - WindowsDaWolfmanView Answer on Stackoverflow
Solution 72 - WindowsbnealView Answer on Stackoverflow
Solution 73 - WindowsMadKatView Answer on Stackoverflow
Solution 74 - WindowspaxdiabloView Answer on Stackoverflow
Solution 75 - WindowsRWendiView Answer on Stackoverflow
Solution 76 - WindowsMark ArnottView Answer on Stackoverflow
Solution 77 - WindowsPhilibert PerusseView Answer on Stackoverflow
Solution 78 - WindowssomeView Answer on Stackoverflow
Solution 79 - WindowsSaschaView Answer on Stackoverflow
Solution 80 - WindowsDeniz ZoetemanView Answer on Stackoverflow
Solution 81 - WindowsleanderView Answer on Stackoverflow
Solution 82 - WindowsCoding With StyleView Answer on Stackoverflow
Solution 83 - WindowssahmeepeeView Answer on Stackoverflow
Solution 84 - WindowsguerdaView Answer on Stackoverflow
Solution 85 - WindowsJohn FisherView Answer on Stackoverflow
Solution 86 - Windowsjon_brockmanView Answer on Stackoverflow
Solution 87 - WindowsjftugaView Answer on Stackoverflow
Solution 88 - WindowsMashmagarView Answer on Stackoverflow
Solution 89 - WindowsjftugaView Answer on Stackoverflow
Solution 90 - WindowsAnonymousView Answer on Stackoverflow
Solution 91 - WindowscookreView Answer on Stackoverflow