Windows Shell Scripting |
About Karen JP - PGP Keys - Vossen's Law - Firefox - MythTV Photos - Deck - SCUBA - Dolphins Security - Firewall Rules - Flypaper - GNATBox - Home - Home Net Security - Principles - Snort - Snort Books - Sec Tools - GenPass - Honeypot Stats - Firewall Stats Source - Perl Networking - Time - NAT - IP Calcs Linux - apt - Edutainment - SME Server - Backup (DI-30) Windows - Win Tools - Voodoo - Win. Shell Scripting - POSIX Redirection - Winlogcheck What's New Email me Email Form |
IntroductionThis article is translated to Serbo-Croatian by WHGeeks. Thanks! The term "shell script" comes from UNIX, the DOS term is "batch files." UNIX shell scripts are very powerful and flexible, they are essentially programming languages unto themselves. Windows or more rightfully DOS batch files are a pale imitation. However, sometimes you need to write something that will just work on any plain old out-of-the-box Windows install someone has--without adding all kinds of other tools. Before getting too deep into this topic, consider if there is another tool you might use. Here is a list of tools, all of which are far more powerful, flexible and are probably easier to use than batch files:
PowershellIf you follow Windows at all you will be aware that Powershell is Microsoft's new command line tool, and that you will be required to use it more and more with newer Windows versions. That is a Good Thing, in my opinion, and it only took them about 20 years to realize, but that is not covered here! I don't really do Windows anymore and I have not bothered to learn Powershell, which reminds me unpleasantly of Java's verbose ugliness. So this page is somewhat historical, though most everything should work to at least Win7. If you are interested in current Windows command line scripting and Powershell (and if you like Windows you should be), there are any number of other resources and books that will help. These are probably good but I haven't read them:
A TweakDid you know that Window's cmd.exe has file and directory name completion, like UNIX shells? It does, and that can be amazingly useful. But in most versions of Windows it's not turned on by default. (I believe it may be on in Windows 2003, but can't swear to it.) To enable file and directory name completion under Windows, download this registry file and remove the .txt, then double-click on it and answer yes to the question about importing into the Registry. If you can't download for some reason you can copy the text below into a new file and import it, or just open regedit, navigate to the key, and change the values for CompletionChar and PathCompletionChar to 9. One you've done that, open a new command prompt and type REGEDIT4 ; NT-TAB.reg -- Sets the NT Command Completion Character to TAB ; Use "RegEdit /s NT-TAB.reg" for silent installations ; v1.0 1998-10-22 JP Vossen The DirtOK, if you are still going to go through with this, the first thing you need is Tim Hill's Windows NT Shell Scripting, otherwise you don't have a chance. For Windows 9x/ME, you are still toast, but for NT/2000 this book is really great. It's the only way you can navigate the bazaar, inconsistent, contradictory and often asinine "scripting" language built into cmd.exe. Using material from that book, plus my own almost 20 years experience with DOS batch files, I still had a hell of a time writing the following script. All it does is give you some basic file information (similar to UNIX stat) and tell you if a file will fit on a floppy disk. The ScriptsClicking on the name of a script will open that script in a new window.
Simple SleepAnother of the many lacking tools is a simple "sleep" command, but you can easily fake that using the "ping" command of all things. The following will "sleep" for about 5 seconds, give or take:
Obviously you adjust the 5 as needed for the number of seconds. You can even write a trivial "sleep" function in your scripts: @echo off REM sleep_demo.cmd--Simple "sleep" command demo REM 2012-07-26 echo Before sleep call :sleep 7 echo After sleep REM End of Main program REM ################################################################### goto :EOF REM +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ REM sleep for a specified number of seconds, more-or-less... REM Called like: call :sleep 7 :sleep set sleep_secs=%1 ping -n %sleep_secs% localhost > NUL goto EoF The DateHow to get and use dates and time in Windows scripts.This is trivially easy in UNIX. You want to copy a log file to a dated name? "cp mylog `date '+%Y-%m-%d'`-mylog" will copy mylog to 2002-11-27 (as of this writing). What could be easier? But in Windows, it sucks. There are two basic ways to approach this, both with advantages and disadvantages. The native way is the "for" and "date /t" commands under NT/2000/XP. These do NOT work under Windows 9x and they do not consistently use 2 digit time fields, which totally screws you up if you need the time. The second way is to use the UNIX date command, then do whatever you please. This is very flexible, but requires you to download and have the executable (date) handy. You will also want to rename it (I use udate.exe) so you don't conflict with the built-in date command. UPDATE (2012-07-26): All versions of Unix "date" commands that I have tested under both WinXP and Win7 have a bug that causes them to skip skip Mar-11 and/or Apr-04! That's pretty annoying but has never been fixed as far as I know. Since it affects both tools I've tested (UnxUtils and GNU Win32), I suspect the Windows strftime lib is the problem. But I can't prove it. And someone else replied to the bug he could not reproduce the problem. So I'd say it's something I'm doing, but I find it off that both the WinXP I've been using forever and a much newer Win7 do the same thing. UPDATE (2003-06-07): Here is a third way that's trivial! It seems there are built-in but undocumented environment variables %time% and %date% in Windows 2000. I have not tested other platforms (let me know if you do). Due to the format, you can't easily use the date in file copy operations (for example), but the time should be OK. And it's by far the easiest option if you are just going to display (writing to a log file or something).
Windows Trivial@echo off REM Play with W2K date/time env. vars. echo The date: %date% echo The time: %time% UPDATE (2006-05-11): Here is a another trivial way! Thanks to Richard Blake (RBlake {at} nea {DOT} org) for this great hack. In addition to the above %time% and %date% variables, there is a %VAR:offset,len% construct documented for the SET command, which works elsewhere. As above, the use of a two digit time code can mess you up, but for just the date it will work very well. Code to deal with non zero padded hours is left as an exercise for the reader. C:\tmp> set MyNewFileName=%DATE:~10,4%%DATE:~4,2%%DATE:~7,2%%TIME:~0,2%%TIME:~3,2%%TIME:~6,2% C:\tmp> echo %MyNewFileName% 20060511 21921 This RedmondMag.com Backup Basics in Windows Server 2008 R2 article expands on the same method, but they are not portable because they depend on how your system time is displayed, and that will vary from machine to machine based on locale and user preference. For example, I loath any date/time format except for ISO8601 so I have my Windows formats set as close to that as possible, which then breaks the assumptions in the first block: @echo off REM date_demo.cmd--Simple date parsing demo REM 2012-03-10 echo Current dates (Windows default date format for US) set year=%date:~10,4% set month=%date:~4,2% set day=%date:~7,2% set hour=%time:~0,2% set min=%time:~3,2% set sec=%time:~6,2% echo Date: %date% Time: %time% echo ISO-8601: %year%-%month%-%day%_%hour%:%min%:%sec% echo. echo Current dates (ISO-8601 date format) REM 2012-03-10 set year=%date:~0,4% set month=%date:~5,2% set day=%date:~8,2% set hour=%time:~0,2% set min=%time:~3,2% set sec=%time:~6,2% echo Date: %date% Time: %time% echo ISO-8601: %year%-%month%-%day%_%hour%:%min%:%sec% Other Ways
Getting InputThere are various tools like ask.exe and choice.exe that allow you to get input. There there's an even easier, although undocumented, way: set /P. As in: set /P MyAnswer=Your Prompt Here! That prompts the user with "Your Prompt Here!" and puts whatever they type into %MyAnswer%. Very cool. Simple UtilitiesExcept for FindZero.bat, all of these batch files will work under DOS, or any Windows.
AddPath.bat@path=%1;%path% MCD.bat@md %1 @cd %1 auto-ftp v1.2 1999-09-16Automatically Download a file using FTP (not secure!). CLR.bat@echo off cd c:\ cd d:\ c: cls ver aformat v2.4 2002-11-09Format Floppy with no user prompts. SPrompt.batRequires ANSI.sys, included with DOS & Windows, or PC Magazine's free AnsiCom. @echo off REM SPrompt.bat -- Dynamically Set Prompt REM Created sometime in 1992 REM 03-Mar-1998 JPV REM 19-Feb-1999 JPV Added "neat" prompt from JPS mail list REM Neat PROMPT `$+[%user@$P]%@EXECSTR[if %@LEN[%_CWD] GT 20 ECHOS $_:$s]` prompt $e[0;33;1;44m$P$e[36;44m$G $e[0;37;44m if not "%1" == "" prompt $e[32;1m%1 %2 %3 %4 %5 %6 %7 %8 %9$_$e[33m%prompt% rem prompt $e[s$e[1;7f$e[0;45;37;1m$e[K($z) $d $t$e[u$e[1m$P$e[0m$G $e[0m rem set WINPMT=$e[0;33;1;44mEXIT to Windows$_$P$e[36;44m$G $e[0;37;44m if {%OS%}=={Windows_NT} prompt $P$G WhoAmI.batRequires Microsoft Networking to be installed and active, and the DOS find command. If you have a UNIX find command in the path, you'll probably get a "No such file or directory" error. @echo off echo. net config /yes | find "name" echo. pause Sending e-mailSomething else that is taken for granted on UNIX is the ability to send e-mail from the command line or a script. As usual, windows makes this a challenge. There are a few free and commercial solutions for this, including but not limited to the following list (I've only ever used Blat):
Upload from Frontpage to your ISPI used to use MS FrontPage to maintain this site (don't ask me why). My old IS, did not support FrontPage or its extensions, for excellent security reasons. Using FrontPage to create pages, then uploading them to a hosted site is a gigantic pain in the ass because of the way FrontPage keeps all of its proprietary information in various "_VTI_CNF" and other subdirectories. So simply zipping up the directories and dumping them onto a host is not ideal. So I came up with the following solution. The old code I posted to a Netaxs news group was WRONG in places! THIS stuff works. I don't use this any more, I use GenSite.pl and rsync. Open issues are:
Windows Scripting Resources
I will add more to this page as time allows. If you have a specific question, let me know, I might be able to help. This article is translated to Serbo-Croatian by WHGeeks. Thanks! |
http://www.jpsdomain.org/windows/winshell.html Copyright © 1995-2022, JP Vossen. All rights reserved. Last Modified: $Date: 2012-08-02 02:36:09 -0400 (Thu, 02 Aug 2012) $ |