Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I'm looking for the equivalent of the Unix 'tail' command that will allow me to watch the output of a log file while it is being written to.
If you use PowerShell then this works:
Get-Content filenamehere -Wait -Tail 30
Posting Stefan's comment from below, so people don't miss it
PowerShell 3 introduces a -Tail parameter to include only the last x lines
I'd suggest installing something like GNU Utilities for Win32. It has most favourites, including tail.
I've always used Baretail for tailing in Windows. It's free and pretty nice.
You can get tail as part of Cygwin.
Anybody interested in a DOS CMD tail using batch commands (see below).
It's not prefect, and lines sometime repeat.
Usage: tail.bat -d
tail.bat -f -f
#echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
rem tail.bat -d <lines> <file>
rem tail.bat -f <file>
rem ****** MAIN ******
IF "%1"=="-d" GOTO displayfile
IF "%1"=="-f" GOTO followfile
GOTO end
rem ************
rem Show Last n lines of file
rem ************
:displayfile
SET skiplines=%2
SET sourcefile=%3
rem *** Get the current line count of file ***
FOR /F "usebackq tokens=3,3 delims= " %%l IN (`find /c /v "" %sourcefile%`) DO (call SET find_lc=%%l)
rem *** Calculate the lines to skip
SET /A skiplines=%find_lc%-!skiplines!
rem *** Display to screen line needed
more +%skiplines% %sourcefile%
GOTO end
rem ************
rem Show Last n lines of file & follow output
rem ************
:followfile
SET skiplines=0
SET findend_lc=0
SET sourcefile=%2
:followloop
rem *** Get the current line count of file ***
FOR /F "usebackq tokens=3,3 delims= " %%l IN (`find /c /v "" %sourcefile%`) DO (call SET find_lc=%%l)
FOR /F "usebackq tokens=3,3 delims= " %%l IN (`find /c /v "" %sourcefile%`) DO (call SET findend_lc=%%l)
rem *** Calculate the lines to skip
SET /A skiplines=%findend_lc%-%find_lc%
SET /A skiplines=%find_lc%-%skiplines%
rem *** Display to screen line when file updated
more +%skiplines% %sourcefile%
goto followloop
:end
There are quite a number of options, however all of them have flaws with more advanced features.
GnuWin32 tail is buggy (α β γ) - things like -f just plain don't work.
UnxUtils tail seems better (-f works, but --pid seems not to, -n but not --lines=n fails with -f), but appears to be a dead project.
Cygwin is a big ugly mush, could perhaps just use the DLL and coreutils package - but still has problems like --pid not working with native win32 processes.
If you do not want to install anything at all you can "build your own" batch file that does the job from standard Windows commands. Here are some pointers as to how to do it.
1) Using find /c /v "" yourinput.file, get the number of lines in your input file. The output is something like:
---------- T.TXT: 15
2) Using for /f, parse this output to get the number 15.
3) Using set /a, calculate the number of head lines that needs to be skipped
4) Using for /f "skip=n" skip the head lines and echo/process the tail lines.
If I find the time, I will build such a batch file and post it back here.
EDIT: tail.bat
REM tail.bat
REM
REM Usage: tail.bat <file> <number-of-lines>
REM
REM Examples: tail.bat myfile.txt 10
REM tail.bat "C:\My File\With\Spaces.txt" 10
#ECHO OFF
for /f "tokens=2-3 delims=:" %%f in ('find /c /v "" %1') do (
for %%F in (%%f %%g) do set nbLines=%%F )
set /a nbSkippedLines=%nbLines%-%2
for /f "usebackq skip=%nbSkippedLines% delims=" %%d in (%1) do echo %%d
I've used Tail For Windows. Certainly not as elegant as using tail but then, you're using Windows. ;)
With Windows PowerShell you can use:
Get-Content <file> -Wait
I haven't seen Log Expert anywhere among answers here.
It's customizable and is quite good for going around log files. So far it's the best Windows graphical log viewer for me.
Unfortunately, this software is no longer available. You can read about it on archive.org.
I've used Mtail recently and it seems to work well. This is the GUI type like baretail mentioned above.
Download the tail command, part of Windows Server 2003 Resource Kit Tools from Microsoft itself.
Try Windows Services for UNIX. Provides shells, awk, sed, etc. as well as tail.
Update -: Unfortunately, as of 2019 this system is no longer available on the Microsoft Download Center.
I prefer TailMe because of the possibility to watch several log files simultaneously in one window: http://www.dschensky.de/Software/Staff/tailme_en.htm
DOS has no tail command; you can download a Windows binary for GNU tail and other GNU tools here.
Another option would be to install MSYS (which is more leightweight than Cygwin).
DOS's type works like *nux's cat, though just like cat, it does dump the whole file, so it's not really a true tail, but it's going to be available in a pinch without downloading/installing a true tail substitute.
I just wrote this little batch script. It isn't as sophisticated as the Unix "tail", but hopefully someone can add on to it to improve it, like limiting the output to the last 10 lines of the file, etc. If you do improve this script, please send it to me at robbing ~[at]~ gmail.com.
#echo off
:: This is a batch script I wrote to mimic the 'tail' UNIX command.
:: It is far from perfect, but I am posting it in the hopes that it will
:: be improved by other people. This was designed to work on Windows 7.
:: I have not tested it on any other versions of Windows
if "%1" == "" goto noarg
if "%1" == "/?" goto help
if "%1" == "-?" goto help
if NOT EXIST %1 goto notfound
set taildelay=%2
if "%taildelay%"=="" set taildelay=1
:loop
cls
type %1
:: I use the CHOICE command to create a delay in batch.
CHOICE /C YN /D Y /N /T %taildelay%
goto loop
:: Error handlers
:noarg
echo No arguments given. Try /? for help.
goto die
:notfound
echo The file '%1' could not be found.
goto die
:: Help text
:help
echo TAIL filename [seconds]
:: I use the call more pipe as a way to insert blank lines since echo. doesnt
:: seem to work on Windows 7
call | more
echo Description:
echo This is a Windows version of the UNIX 'tail' command.
echo Written completely from scratch by Andrey G.
call | more
echo Parameters:
echo filename The name of the file to display
call | more
echo [seconds] The number of seconds to delay before reloading the
echo file and displaying it again. Default is set to 1
call | more
echo ú /? Displays this help message
call | more
echo NOTE:
echo To exit while TAIL is running, press CTRL+C.
call | more
echo Example:
echo TAIL foo 5
call | more
echo Will display the contents of the file 'foo',
echo refreshing every 5 seconds.
call | more
:: This is the end
:die
The tail command and many others are available in the Windows Resource Kit Tools package.
If you want to use Win32 ports of some Unix utilities (rather than installing Cygwin), I recommend GNU utilities for Win32.
Lighter weight than Cygwin and more portable.
Install MKS Toolkit... So that you can run all Unix commands on Windows.
The command is:
tail -f <file-name>
In Far Manager, press F3 on a file to enter the standard viewer, then the End key to navigate to the end of file.
If the file is updated, Far Manager will scroll it automatically.
Graphical log viewers, while they might be very good for viewing log files, don't meet the need for a command line utility that can be incorporated into scripts (or batch files). Often such a simple and general-purpose command can be used as part of a specialized solution for a particular environment. Graphical methods don't lend themselves readily to such use.
You can try WinTail as well.
ََ
I think I have found a utility that meets the need for the tail function in batch files. It's called "mtee", and it's free. I've incorporated it into a batch file I'm working on and it does the job very nicely. Just make sure to put the executable into a directory in the PATH statement, and away you go.
Here's the link:
mtee
I'm using Kiwi Log Viewer. It's free.
Related
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about a specific programming problem, a software algorithm, or software tools primarily used by programmers. If you believe the question would be on-topic on another Stack Exchange site, you can leave a comment to explain where the question may be able to be answered.
Closed 9 years ago.
Improve this question
I would like to get into batch file processing for Windows, but I have zero experience in this area. If you can point me in a general direction, it would be greatly appreciated.
Other potential questions:
What are the risks to be avoided with batch processing?
What is the basic structure of a batch file?
Are there examples of basic types of batch files, where I can put into action?
What are some basic types of batch commands?
Bach is a very methodical and ordered programming language that runs heavily on the Windows internal CMD or runline commands you're most likely familiar with. The main use of Batch from my personal experience is to use scripts to automate mundane tasks that need to be run every time something happens, for example at user startup.
I bet you could quite easily make a basic script now just buy learning what a) every bactch file should ideally have/need and b) by recognising that by default a batch file will read from top to bottom executing one command after the previous one finishes or fails.
In answer to your specific questions:
The risks to batch processing aren't really existent if you script something properly and test it every step of the way. - I would of said that anyone can easily see your code but third party tools will convert batch to .exe files without a problem.
I've listed some example codes with a few explanations at the bottom of this answer.
Again see the bottom of my answer for some basic scripts that will work on your computer (providing it's a version of Windows).
As I mentioned above any command you can type in to a CMD window will work within a batch file, so you can use command /? within a CMD window to check parameters and the way you should write your commands. For example type in to a CMD window ipconfig /?.
Basic Batch File Structure (Save as test.bat)
#echo off
title Test Batch Script
color a
echo.
ipconfig /all
echo.
echo Above is your IP information.
pause>nul
exit
#echo off - This turns off the CMD prompt until turned on again, without this every action is displayed, on the above script remove the line or turn it on to see the effects.
title - This is quite self explanitory, this command titles the CMD window to your choosing.
color xx - color xx changes the colour of the background and text, the first value is the text and the second is the window background. - Use color /? in a CMD window to find all the possible combinations and choose one for yourself, for example color 1f
echo. - This will enter a line break in to the file itself, I use this mainly for spacing text or adding a few lines under commands so my text can be seen clearly after commands have run.
echo - This will print the line of text you're trying to say, for example echo hello will display the text hello in the window.
pause>nul - This will pause the batch script from advancing to the next command in the series. - however just using the command pause will display the text "Press any key to continue..." using pause>nul will remove this message. Not essential but personal preference really.
exit - Exit will of course close your program, however not necessary when batch scripting as the script will close when no more commands are left to run, providing that no user input is required.
I feel that I've given you a basic and common batch file using all the most common commands that you'll use nearly every time you make a batch file.
The other answers have listed a lot of resources you can use to learn more. - Batch is an extremely easy language to learn but can get tricky depending on how much user input is required or how automated you want to make something.
Get to grips with my example and replace ipconfig /all with different/multiple commands to practice using them within your scripts.
In relation to the risks inolvd with batch programming, the worst that can happen is that when working with some files on your computer your batch script may malfunction, causing the files to be either erased or ruined. That is why, it is recommended to back-up all files before testing a batc script.
The basic structure of a batch file varies quite oftenly. When you start of you will mostly rely on goto loop structures. Where your script will start of with a series of commands (normally the first one being #echo off) and then making the script goto diffferent parts of your program.
Later on you will rely on for loops and batch calling.
To find some half decent batch app's I recommend you look online as there are some sights which can contain quite a few.
For basic tutorials, I recommend you start of by making simple batch apps to do very basic things like count.
Hope this helped, Mona.
P.S. Here are some I recently uploaded some of my old batch apps on instructables, here are the links:
Naughts and crosses
Calculator + Tutorial
Encryption with 7zip
go to http://www.dostips.com/
list of basic commands:
echo hello world ::will write hello world to the screen
echo %time% :: will write the value of the variable time to the screen
cd dir ::will go into the directory named dir
type file.txt ::will print the contents of a file to the screen
dir ::will echo the contents of the current directory to the screen
cd .. ::will goto the parent directory
help :: will show a list of commands
set ::will show all current variables
if "%var%" EQU "hello" (echo is) ::will echo is if the varible var is set to hello
set var=hello ::will set var equal to hello
set /p var=how are you: ::will get input from the user and stroe it in var
for /l %%i in (1,1,5) do echo %%i ::will echo 1 to five on the screen
ping host.com ::will check if you can connect to host.con and diplay some results.
copy a.txt dir\dir2\b.txt ::will copy a.txt to the second argument.
move a.txt ..\a.txt ::will move a.txt to the parent directory.
ren a.txt b.pdf ::will rename a.txt to b.pdf
command /? ::will display help on a command
here are some sample files I made:(blank lines matter)
file1:
setlocal enabledelayedexpansion
set NLM=^
set NL=^^^%NLM%%NLM%^%NLM%%NLM%
for /f "delims=" %%i in (a.txt) do set a=!a!!nl!%%i
echo %a%
file2:(each for is a single line)
#echo off&setlocal enabledelayedexpansion
if '%1'=='' (echo missing parameter&pause>nul&exit /b)
for /l %%i in (%1,-1,0) do for /l %%j in (%%i,1,%1) do set %%i=!%%i!
for /l %%i in (0,1,%1) do (for /l %%j in (0,1,%%i) do set nums=!nums! %%j)&echo !%%i!!nums!&set nums=
for /l %%i in (%1,-1,0) do (for /l %%j in (0,1,%%i) do set nums=!nums! %%j)&echo !%%i!!nums!&set nums=
file3:
setlocal enabledelayedexpansion
for /f "delims=" %%i in (a.txt) do set a=%%i&set a=!a:""=! &echo !a!>>new.txt
file4:(for is one line)
#echo off
for /d %%i in (*) do for /f %%j in ("%%i") do (dir "%%i" /b|for /f %%k in ('find "%%j" /v') do #dir "%%k" /b /s|find "thumbs.db" /v)
email me if you have questions. I know batch better than any other language and love it. my email is: 12nephi12#gmail.com
have fun!!! ;)
I am writing a simple batch file (remove.bat) to remove a directory and all its subdirectories. The file contains the following command-
rmdir /S modules
where modules is the name of the non-empty directory.
I get the following message -
C:\...\bin>rmdir /S modules
modules, Are you sure (Y/N)?
How can I supply through the batch file the console input "Y" to the Y/N question above? Is there a command that can do this?
As others have pointed out, you should use the /Q option. But there is another "old school" way to do it that was used back in the day when commands did not have options to suppress confirmation messages. Simply ECHO the needed response and pipe the value into the command.
echo y|rmdir /s modules
I recommend using the /Q option instead, but the pipe technique might be important if you ever run into a command that does not provide an option to suppress confirmation messages.
Note - This technique only works if the command reads the input from stdin, as is always the case with cmd.exe internal commands. But this may not be true for some external commands.
Do rmdir /S for deleting a non-empty directory and do rmdir /Q for not prompting. Combine to rmdir /S /Q for quietly delete non-empty directories.
Use rmdir /S /Q modules
/Q suppresses the confirmation prompt.
You can do
rmdir /Q
Q is for quiet
If you are not dealing with a windows with a english/us locale you might need to retrieve the answers needed for your machine:
#echo off
setlocal
set "ans_yes="
set "ans_no="
set "ans_all="
copy /y nul # >nul
for /f "tokens=2-7 delims=[(/)]" %%a in ( '
copy /-y nul # ^<nul
' ) do if not defined ans_yes if "%%~e" == "" (
set "ans_yes=%%~a"
set "ans_no=%%~b"
set "ans_all=%%~c"
) else (
set "ans_yes=%%~a"
set "ans_no=%%~c"
set "ans_all=%%~e"
)
del /q #
set "ans_yes=%ans_yes: =%"
set "ans_no=%ans_no: =%"
set "ans_all=%ans_all: =%"
set "ans_y=%ans_yes:~0,1%"
set "ans_n=%ans_no:~0,1%"
set "ans_a=%ans_all:~0,1%"
endlocal & (
set "ans_y=%ans_y%"
set "ans_n=%ans_n%"
set "ans_a=%ans_a%"
)
echo %ans_y%|rmdir /s modules
YES.EXE
Yes is a fantastic tool that will continually answer Yes, No or whatever to any process that is asking for input.
If you run it by itself, it just outputs y + enter over and over. But that's not really what it's meant for. It's meant for piping into another program that is looking for a response to a prompt.
The simplest use case:
yes|rd temp /s
You can use yes.exe to output any argument or string: (stupid example warning):
yes hello world for a simple basic 10 PRINT "Hello World": GOTO 10
What it's really for:
It's meant for command line tools that can have a repetitive prompt but don't have a built-in /y or /n.
For example, you're copying files and keep getting the Overwrite? (Yes/No/All) prompt, you get stuck having to hammer to "N" key for No. Here's the fix:
yes n|copy * c:\stuff
How to get it?
This is just a small part of the GNU Core Utils for Windows, which provides the basic Linux commands to Windows people. VERY, VERY useful stuff if you write a lot of batch files.
If you have Git for Windows, you already have it, along with the rest of the GNU Core Utils. Check your PATH for it. It's probably in C:\Users\USERNAME\AppData\Local\Programs\Git\usr\bin
If you need to download the Windows binaries, they're available from a lot of different places, but the most popular is probably at https://cygwin.com/packages/summary/coreutils.html
I just want to add that, although not applicable to Rmdir, a force switch may also be the solution in some cases. So in a general sense you should look at your command switches for /f, /q, or some variant thereof (for example, Netdom RenameComputer uses /Force, not /f).
The echo pipe is a neat trick and very useful to keep around since you wont always find an appropriate switch. For instance, I think it's the only way to bypass this Y/N prompt...
Echo y|NETDOM COMPUTERNAME WorkComp /Add:Work-Comp
Link to nearly identical StackOverflow post
Say I have a program X.EXE installed in folder c:\abcd\happy\ on the system. The folder is on the system path. Now suppose there is another program on the system that's also called X.EXE but is installed in folder c:\windows\.
Is it possible to quickly find out from the command line that if I type in X.EXE which of the two X.EXE's will get launched? (but without having to dir search or look at the process details in Task Manager).
Maybe some sort of in-built command, or some program out there that can do something like this? :
detect_program_path X.EXE
Use the where command. The first result in the list is the one that will execute.
C:\> where notepad
C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe
According to this blog post, where.exe is included with Windows Server 2003 and later, so this should just work with Vista, Win 7, et al.
On Linux, the equivalent is the which command, e.g. which ssh.
As the thread mentioned in the comment, get-command in powershell can also work it out. For example, you can type get-command npm and the output is as below:
Here's a little cmd script you can copy-n-paste into a file named something like where.cmd:
#echo off
rem - search for the given file in the directories specified by the path, and display the first match
rem
rem The main ideas for this script were taken from Raymond Chen's blog:
rem
rem http://blogs.msdn.com/b/oldnewthing/archive/2005/01/20/357225.asp
rem
rem
rem - it'll be nice to at some point extend this so it won't stop on the first match. That'll
rem help diagnose situations with a conflict of some sort.
rem
setlocal
rem - search the current directory as well as those in the path
set PATHLIST=.;%PATH%
set EXTLIST=%PATHEXT%
if not "%EXTLIST%" == "" goto :extlist_ok
set EXTLIST=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
:extlist_ok
rem - first look for the file as given (not adding extensions)
for %%i in (%1) do if NOT "%%~$PATHLIST:i"=="" echo %%~$PATHLIST:i
rem - now look for the file adding extensions from the EXTLIST
for %%e in (%EXTLIST%) do #for %%i in (%1%%e) do if NOT "%%~$PATHLIST:i"=="" echo %%~$PATHLIST:i
Assuming Windows, is there a way I can detect from within a batch file if it was launched from an open command prompt or by double-clicking? I'd like to add a pause to the end of the batch process if and only if it was double clicked, so that the window doesn't just disappear along with any useful output it may have produced.
Any clever ways to do this? I'm looking for solutions I could rely on to work on a machine that was configured more or less with default settings.
I just ran a quick test and noticed the following, which may help you:
When run from an open command prompt, the %0 variable does not have double quotes around the path. If the script resides in the current directory, the path isn't even given, just the batch file name.
When run from explorer, the %0 variable is always enclosed in double quotes and includes the full path to the batch file.
This script will not pause if run from the command console, but will if double-clicked in Explorer:
#echo off
setlocal enableextensions
set SCRIPT=%0
set DQUOTE="
#echo do something...
#echo %SCRIPT:~0,1% | findstr /l %DQUOTE% > NUL
if %ERRORLEVEL% EQU 0 set PAUSE_ON_CLOSE=1
:EXIT
if defined PAUSE_ON_CLOSE pause
EDIT:
There was also some weird behavior when running from Explorer that I can't explain. Originally, rather than
#echo %SCRIPT:~0,1% | findstr /l %DQUOTE% > NUL
if %ERRORLEVEL% EQU 0 set PAUSE_ON_CLOSE=1
I tried using just an if:
if %SCRIPT:0,1% == ^" set PAUSE_ON_CLOSE=1
This would work when running from an open command prompt, but when run from Explorer it would complain that the if statement wasn't correct.
Yes. Patrick Cuff's final example almost worked, but you need to add one extra escape, '^', to make it work in all cases. This works great for me:
set zero=%0
if [^%zero:~0,1%] == [^"] pause
However, if the name of the batch file contains a space, it'll be double quoted in either case, so this solution won't work.
Don't overlook the solution of having two batch files:
abatfile.bat and abatfile-with-pause.bat
The second simply calling the first and adding a pause
Here's what I use :
rem if double clicked it will pause
for /f "tokens=2" %%# in ("%cmdcmdline%") do if /i "%%#" equ "/c" pause
I use a parameter "automode" when I run my batch files from scripts.
set automode=%7
(Here automode is the seventh parameter given.)
Some code follows and when the file should pause, I do this:
if #%automode%==# pause
One easy way to do it is described here:
http://steve-jansen.github.io/guides/windows-batch-scripting/part-10-advanced-tricks.html
There is little typo in the code mentioned in the link. Here is correct code:
#ECHO OFF
SET interactive=0
ECHO %CMDCMDLINE% | FINDSTR /L /I %COMSPEC% >NUL 2>&1
IF %ERRORLEVEL%==0 SET interactive=1
ECHO do work
IF "%interactive%"==1 PAUSE
EXIT /B 0
Similar to a second batch file you could also pause if a certain parameter is not given (called via clicking).
This would mean only one batch file but having to specify a -nopause parameter or something like that when calling from the console.
crazy idea: use tasklist and parse it's results.
I've wrote in a test batch file:
tasklist > test.out
and when I double-clicked it, there was an additional "cmd.exe" process just before the tasklist process, that wasn't there when the script was run from command line (but note that might not be enough if someone opens a command line shell and then double-click the batch file)
Just add pause regardless of how it was opened? If it was opened from command prompt no harm done apart from a harmless pause. (Not a solution but just thinking whether a pause would be so harmful / annoying )
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
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?)
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
PUSHD path
Takes you to the directory specified by path.
POPD
Takes you back to the directory you "pushed" from.
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.
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
Variable substrings:
> set str=0123456789
> echo %str:~0,5%
01234
> echo %str:~-5,5%
56789
> echo %str:~3,-3%
3456
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...
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.
The path (with drive) where the script is : ~dp0
set BAT_HOME=%~dp0
echo %BAT_HOME%
cd %BAT_HOME%
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\LONGDI~1\test.bat
\Temp\LONGDI~1\
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
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.
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
Escaping the "plumbing":
echo ^| ^< ^> ^& ^\ ^^
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
Creating an empty file:
> copy nul filename.ext
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.
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.
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.
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%
Integer arithmetic:
> SET /A result=10/3 + 1
4
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.
Output a blank line:
echo.
You can chain if statements to get an effect like a short-circuiting boolean `and'.
if foo if bar baz
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.
if block structure:
if "%VS90COMNTOOLS%"=="" (
echo: Visual Studio 2008 is not installed
exit /b
)
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
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
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.
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 ?
Total control over output with spacing and escape characters.:
echo. ^<resourceDir^>/%basedir%/resources^</resourceDir^>
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