Manipulating file names in command shell script

This has nothing to do with XML.

I have been helping out another team here in the SQL Engine with some of their lab automation. Most of it consists of tons of shell scripts, which isn't necessarily a bad thing, but I am certainly no shell scripting expert. At any rate, I was faced with the following problem: figure out the path to the batch file which is being executed. Now, I am sure that to you shell scripting gurus this doesn't sound like much of a challenge, but like I said already, I am not really up to speed on shell scripting. 

One of my coworkers thought that there was some simple way of doing it directly in the command interpreter, and wouldn't require external programs or anything like that. He also left a small clue in that he seemed to recall that the syntax looked like regular variable-referencing syntax, and probably had a "d" and a "~" in it. Well, I challenge you to use a search engine to find something with a "~" and a "%" in it.

After about 10 minutes of msnsearching and googling without really finding anything, I decided start looking through all of the other batch files on my machine to see if I could run across something that looked promising. I have two tools which aided me greatly here, the first was the desktop search stuff in the new MSN Toolbar, the second was that I was looking for something which had a "%" relatively close to a "~". I used the following desktop search string: 'ext:bat "~" "%"' and within moments I came across what I was looking for: %~dp0.

So how does this work? Well lets say you are running a batch named bar.bat, and it is located in c:\foo. %~dp0 will return the path "c:\foo" regardless of where I am actually executing the file from (well... not exactly, but it will give me a fully qualified path that "works"... even if that path is a network share or something). The reason is that the "~" character turns on the command interpreters special "manipulation" mode (I don't think that is what _they_ really call it, but it works for me), from there you can provide several modifiers which manipulate the filename. In this case, "d" tells it to output the drive in which the file lives on, and "p" tells it to output the path within that drive to the file. In the example above, "d"="c:", and "p"="\foo". You can generally apply these modifiers to any of the command line arguments to your script file. There are even some others:

  • %~0 = remove surrounding quotes
  • %~f0 = expand to fully qualified path
  • %~d0 = expand to drive letter
  • %~p0 = expand to path only
  • %~n0 = expand to filename only
  • %~x0 = expand to extension only
  • %~s0 = expand to short path name
  • %~a0 = expand to attributes only
  • %~t0 = expand to date/time of the file
  • %~z0 = expand to size of the file

Of course, all of these can be stacked just like my use case of %~dp0.