Date: | January 28, 2005 / year-entry #26 |
Tags: | tipssupport |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050128-00/?p=36573 |
Comments: | 37 |
Summary: | Sometimes people go to great lengths to get information which is available in a much simpler way. We saw it a few days ago when we found a 200+-line C# program that could be replaced with a 90-byte batch file. Here's another example of a rather roundabout way of capturing the current directory from a... |
Sometimes people go to great lengths to get information which is available in a much simpler way. We saw it a few days ago when we found a 200+-line C# program that could be replaced with a 90-byte batch file. Here's another example of a rather roundabout way of capturing the current directory from a batch file.
The easy way is to use the set OLDDIR=%CD% .. do stuff .. chdir /d %OLDDIR% &rem restore current directory (Of course, directory save/restore could more easily have been done with pushd/popd, but that's not the point here.)
The set _=%CD%\curfile.txt cd ... some other directory ... somecommand args %_% args
(I like to use
Type |
Comments (37)
Comments are closed. |
That is undeniably useful, but more often I find myself wanting to find the directory that a specific batch file is in from inside that batch file, which is a bit more awkward.
Half the time I end up doing something like this:
:: Change to the directory that this batch file is in
:: NB: it must be invoked with a full path!
for /f %%i in ("%0") do set curpath=%%~dpi
cd /d %curpath%
Why not use pushd/popd? No need to use an environment variable at all.
pushd … some other directory …
.. do stuff ..
popd &rem restore current directory
Um, try reading past the third paragraph.
Doh! Sorry.
I’ve written some stuff for myself that stores the current directory to a file on the current drive.
A program reads that file, and switches to that directory on the current drive. Very handy for
1. Crash recovery on pre-XP machines
2. Getting back to where I was on my Laptop.
Ryan
Raymond stated
"
(Of course, directory save/restore could more easily have been done with pushd/popd, but that’s not the point here.)
"
The post under the second link is useful because it solves the general problem of capturing output from an external program. %CD% is an easier solution but only for a specific problem of getting the current directory.
The best way to do this stuff is, IMHO, to install Cygwin or similar and write Bash scripts.
Works as well:
cd /d %~dp0
If you want to know where the batch file lives: %~dp0
%0 is the name of the batch file. ~dp gives you the drive and path of the specified argument.
I use this technique a lot for automating eMbedded Visual C++ builds. The command-line build environment is pretty tricky to use for Windows CE, so I just use evc /make. Well, actually I use a C# program I wrote which looks up in the registry where eVC is installed and runs evc.com from either eVC 3.0 or eVC 4.0 depending on the command line argument passed, or if no version is specified, on the first line of the workspace file.
For most of my projects I’ve now got down to the holy grail of single-command automated builds through a variety of batch files and simple utilities like that one. The ‘buildme’ batch file rebuilds all the components from source then builds a Windows CE installation CAB for potentially many platforms.
Regarding pushd/popd: is there a way to list the content if its stack? I always seem to forget what I’ve pushd’d and if popd will actually take me back where I want.
you can also use SUBST…
"Regarding pushd/popd: is there a way to list the content if its stack? I always seem to forget what I’ve pushd’d and if popd will actually take me back where I want. "
Don’t know if you can get a list of the stack contents, but you can set the prompt to show you how deep the stack is by adding $+ to the prompt. See prompt /? for more info of course. But would be nice to output what the stack is too.. anybody who knows if that is possible?
Didn’t know that one (%CD%).
I use %TEMP% now and then too, if I want to try out a code snippet but don’t need to keep the project. I’ll save the project to %TEMP%.
I’m sure you all know this, but you can use . for
the current directory and .. for the parent of the current directory. Very handy.
"is there a way to list the content if its stack?"
On windows xp, issuing pushd with no args lists the contents of the stack:
C:temp>pushd "Documents and Settings"
C:Documents and Settings>pushd
C:temp
C:Documents and Settings>pushd tools
C:tools>pushd
C:Documents and Settings
C:temp
on other versions of windows, YMMV.
You can use pushd + %CD% to get the canonical version of a path, too:
pushd %MYPATH%
set MYPATH=%CD%
popd
In a lot of my CMD scripts, I use the %RANDOM% pseudo-variable; it’s great for creating temp files that you don’t want to collide with other instances of your script. E.g. foo.cmd:
@if DEFINED _echo @( echo on ) else @( echo off )
:RandomFile
set __foo_ScratchFile=%TEMP%foo.scratch.%RANDOM%.txt
if EXIST %__foo_ScratchFile% goto RandomFile
(
echo Scratch foo content!
echo Second line of content
echo.
echo Fourth line
) > %__foo_ScratchFile%
if EXIST %__foo_ScratchFile% del /f/q %__foo_ScratchFile% > nul 2>&1
There’s a fair amount of fun CMD script fun in there… :)
A commenter on the link that Raymond pointed to up top says:
—–
If you’ve got Cygwin installed, you can use its ‘date’ command to get hold of a suitable suffix for logfiles, e.g.:
for /f "delims=" %%i in (‘c:cygwinbindate +%%Y%%m%%d.%%H%%M%%S’) do set fileSuffix=%%i
Note the doubling of the %-marks in the format string. You need to do this, or you’ll end up with a suffix of "mHS".
—–
You don’t need the for loop in this example, either. In other situations, for /f is very, very useful, but for this, you can just do this [assuming your locale is English (United States)]:
set fileSuffix=%DATE:~-4%%DATE:~4,2%%DATE:~7,2%.%TIME:~0,2%%TIME:~3,2%%TIME:~6,2%
@REM %TIME% Puts a leading space on hours if < 10, change to 0
set fileSuffix=%fileSuffix: =0%
The big drawback is that %DATE% and %TIME% are formatted according to your locale, so this method of parsing isn’t universal. :/
<p>… I don’t need a verbose language to program in!</p>
<p>For the longest time I thought that the equivalent of backticks in UNIX (substituting `*cmd*` with the output of *cmd*) was impossible in Windows. It probably is impossible pre-Win2k, but I ha
You have to admit that one reason for the weird circumlocutions you see in people’s batch code is that the documentation is so woeful. Suppose I want to know how to extract the year from the DATE pseudovariable. What’s the command to get that information? Why, it’s explained in the help for the SET command. How obvious. And if I want to know the matching syntax for splitting the %0, %1 and other variables, where’s that explained? So far the answer seems to be: in Raymond Chen’s weblog.
I would dearly like to see something that explains all of it – pseudovars, the arcane and inane rules of expansion, what registry setting to tweak if you want command completion — everything. I suggest the ideal name would be MAN – Microsoft’s Arcane Nuances.
2Eric TF Bat
I found this Usenet group "
microsoft.public.win2000.cmdprompt.admin" invaluable when dealing with CMD.EXE. There is much esoteric knowledge shared out there by very skillful individuals.
On a somewhat related topic, since a number of people have mentioned CD /D:
Why isn’t /D idempotent (on Windows 2000, anyway)?
CD /D /D <fullPath>
does nothing.
This is problematic for scripts, because you don’t know if someone has used doskey to alias CD to CD /D, and AFAICT there’s no way for a script to unload doskey aliases.
Try running %windir%helpntcmds.chm – don’t know if it covers everything though.
On NT4:
> echo %CD%
%CD%
Loz,
If I’m reading the documentation correctly, %CD% is a pseudo-variable only available to set. It’s not a real environment variable, so it’s not generally available.
You can make it generally available like this, however:
set CD=%CD%
…but you must remember to update the variable every time you change the current working directory, of course.
It’s been so long since I wrote batch files. I remember writing a pretty text-based menu system using ANSI.SYS and CHOICE in MS-DOS many moons ago. Fun times. Lots of the new additions made in CMD would have made life so much easier for me writing that!
Scratch my last comment. I didn’t actually test to see if echo would honour the pseudo-variable on my Windows 2000 system, but it did. I think I’ll refrain from commenting any further on this, because I’m just going to end up embarassing myself. ;)
Yes!
Why the heck can’t we just have backquotes in Windows batch? It’s not like it’s a new idea. I’ve been using them since I was a teenager, and I’m ancient!
You can – see "for /?" and "usebackq".
The problem is how to add these features without breaking existing batch files.
Don’t forget to handle spaces in path and file names. Note for example the difference between how cd and chdir operates with and without command extensions enabled.
You miss my point, Raymond. I should be able to use backquotes with "set" or even some random exe like notepad, as in "notepad.exe
lookformyfiles.exe
". I don’t mind having to call some "setbatchoptions" commmand to turn the feature on if I have to. Don’t get me wrong – I’ll use "for" to do this, but I’m much more likely to require every machine I work on to have perl or some other tool I have to support.But if you turn the feature on, it will break batch files that weren’t written to be compatible with "setbatchoptions". For example, a batch file that says
echo
Hello'
Hello’. Maybe batch file backwards compatibility isn’t important to you, but it is to an awful lot of corporate system administrators who deploy batch files throughout their company.<br>
<br>will now get an "unmatched backquotes" error instead of printing
If you want ksh you know where to find it.
http://weblogs.asp.net/oldnewthing/archive/2005/01/24/359496.aspx
The problem: where’s the script?
Your script or application needs to locate other files or directories…
Otherwise file names won’t resolve.
PingBack from http://www.xerxesb.com/2008/switching-an-iis-website-home-directory-from-the-command-line/
PingBack from http://www.markhneedham.com/blog/2008/08/12/getting-the-current-working-directory-from-dos-or-batch-file/