Date: | May 11, 2007 / year-entry #167 |
Tags: | tipssupport |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20070511-00/?p=26893 |
Comments: | 46 |
Summary: | To execute a command in each subdirectory of a directory tree from a batch file, you can adapt the following: for /f "delims=" %%i in ('dir /ad/s/b') do echo %%i (If you want to play with this command from the command prompt, then undouble the percent signs.) The /F option enables various special behaviors of... |
To execute a command in each subdirectory of a directory tree from a batch file, you can adapt the following: for /f "delims=" %%i in ('dir /ad/s/b') do echo %%i (If you want to play with this command from the command prompt, then undouble the percent signs.)
The
The option we provide, The command request to be performed for each line is simply echoing the directory name. In real life, you would probably put something more interesting here. For example, to dump the security descriptor of each directory (which was the original problem that inspired this entry), you can type this on the command line: for /f "delims=" %i in ('dir /ad/s/b') do cacls "%i" >>"%TEMP%\cacls.log" Nitpicker's corner I doubt anybody actually enjoys working with batch files, but that doesn't mean tips on using it more effectively aren't valid. |
Comments (46)
Comments are closed. |
Batch files! NOOOOOOOOOOOOOOOOOOOoooooooooooooooooo……….
splat.
Alternatively:
for /r /d %%i in (*) do echo %%i
Or the other alternative (using cygwin)
find -type d -exec echo ‘{}’ ‘;’
I do think the cygwin way of doing this kind of thing is substantially friendlier…
I prefer to use Windows Script Host for these kind tricks. The clumsiness of FileSystemObject can be hidden with some functions and you have all of Javascript (or VBScript) at your disposal for string operations. All the infrastructure is already down on the drive, at least since Windows 95.
"You make it sound like you have to re-install perl every time you want to write a perl script."
And what if you do? For instance, you’re trying to debug a problem on a customer’s PC that you’ve never seen before.
"Umm, do you mind if I install perl, Visual Studio, and Photoshop first before I can start debugging this issue?"
You know, you can use your head and figure out whether it really does cause you two problems instead of taking Raymond’s word as gospel instead of advice. If it turns out it doesn’t cause you two problems, then good for you! You deserve a treat for figuring that out yourself.
This is a microsoft blog right? You never tried powershell I guess? Maybe you have heard of it. Its something your company makes.
Might as well mention "for /r /d %I in (.) do @echo %I" as well, which seems to be the method that whoever wrote the help text for the for command recommends. You get names that end in ., but it lists directories that (*) misses.
Quoting Abraham Lincoln for a discussion on corporate IT – brilliant. Totally misunderstanding the quote and using it in absolutely the wrong context – priceless.
Is there any good documentation on the syntax for batch files? We have some homegrown scripts to do various things but some things are extremely hard to figure out, like how to deal with parentheses in strings, which comes up when trying to parse a PATH envvar on x64 systems for example.
It’s humiliating (but mostly frustrating) for an expert C++ programmer to spend three hours figuring out how to append a string to another… in the end I wrote a .net app in five minutes to solve the problem.
"This is a microsoft blog right? You never tried powershell I guess?"
I am pretty sure Raymond was looking to work with the tools already available on the island. That’s why I mentioned WSH as an alternative as well. If you’re going to download and MSH, Perl, Python, whatever on 100 or 1000 computers to solve a simple admin problem then you are wasting time.
Not really – there’s 3 decent resources for Windows batch scripting that I know of:
1) cmd.exe’s help facility (just type "help" or use the /? option for the command you want specific help on).
2) Tim Hill’s book "Windows NT Shell Scripting" (http://www.amazon.com/dp/1578700477/)
3) Google
Unfortunately, cmd’s batch syntax seems to have grown more or less organically, rather than been designed. In particular the behavior for quoting characters and strings can be strange an unintuitive. So it can be quite painful to do much in the way of string manipulation.
Thanks for the tip, batch files are still good for a lot of things.
And when I need something more powerful, I have discovered a cool tool a while ago: KiStart http://www.kixtart.org/index.asp
Needs no installation (just drop 2 files with your script), and has a scripting language, can do ole automation, registry access, reading files, etc, and.
Sure, Perl, Awk, PowerShell, have their place and I use them. But knowing more tools allows you to choose the best for the job.
@bionicbee: If all you want is documentation on commands, search for "command processor" in MSDN, or try "help whatever" at the command-line.
For more in-depth stuff, I highly recommend "Windows NT Shell Scripting" by Tim Hill.
http://www.amazon.com/Windows-Shell-Scripting-Timothy-Hill/dp/1578700477
What’s your point? The fact that PowerShell exists makes old-fashioned batch files useless now? All those little .cmd files in my util directory have not seemed to notice.
This is a usefull tip. I’m always surprised by how much you can do with the command language in Windows. There’s quite a lot you can do using it without having to go into other applications.
“[You have to install it on every computer that will run your script, which in a corporate setting can be hundreds or thousands. At some point, the trade-off will be worth it, and you can ignore all my batch file tips. Until then, the tips are there. -Raymond]”
But for your tips, I would need to install Windows.
Eek.
I do this kind of thing all the time. There’s a certain punk cachet in doing cool things with batch that I enjoy. Sort of a question (although this should maybe have gone to the suggestion box): do you know why usebackq isn’t the default? It seems slightly odd to me that since a “syntax” for “run a command and get its output” already existed (backticks) that cmd.exe implemented a different one (single quotes) and then put in the backticks as a config option. This might not be a Raymond question at all; I don’t know whether the command shell comes under the aegis of the shell team, ironically enough!
Stuart: thank GOD it isn’t the default. It is a PAIN to type backquotes on certain keyboard layouts. Also I think single quotes came first and the alternate syntax was added later
Raymond: ah, OK, if I’ve got it backwards then I was wrong. Not sure what I’ve got backwards, mind :)
KJK::Hyperion: backticks are awkward to type? I clearly don’t have as much experience of alternate keyboard layouts as I need, then!
Stuart: Alt-096 on an Italian layout…
>
>
I dunno… I’m a big fan of Cygwin myself, and I think that the way Raymond showed was far more readable.
To be fair, in a corporate setting, installing Monad on hundreds or even thousands of computers is only about ten times as difficult as setting it up on one computer.
I realize it’s not exactly the point of this post, but for anyone who is interested, you might check out the free AutoIt (http://www.autoitscript.com/autoit3/). It has an incredibly full-featured API that lets you do nearly anything you’d want to on Windows. The syntax is a lot like Visual Basic, and you can compile the scripts into a standalone executable, so no need to install libraries, etc.
In any case, it has been very helpful for me in the past.
Also, http://www.robvanderwoude.com/batchfiles.html is an invaluable resource for those who would invest some time in learning the Windows command line.
[Woo-hoo, now I have two problems. -Raymond]
Yes, but if you solve one of them *once*, it makes *all your other* problems easier to solve from then on. If you’d installed cygwin/perl/monad/whatever last March when it was originally suggested, you’d have *already* solved that problem, and would be able to solve this one more easily.
You make it sound like you have to re-install perl every time you want to write a perl script.
“Give me six hours to chop down a tree and I will spend the first four sharpening the axe.”
— Abraham Lincoln
Using batch files to accomplish all your automation goals is like trying to cut down all your trees with a rusty axe. If you could just take a day to leave the forest, find civilisation, and buy a damn chainsaw, you’ll make the time up later. Honest.
“No, no, I can’t take the time out to go and find proper tools – I’m too busy doing it slowly!”
“You make it sound like you have to re-install perl every time you want to write a perl script.” – Adam
You are assuming you got the go ahead to install <whatever your technology of choice is by whatever vendor of choice> in the first place – as Raymond points out in the linked article this is not always trivial or even possible.
If you can dump the permissions of a file system tree on a production server to a file without installing and other software (which could introduce new security issues, training requirements etc.) then surely one line typed in at a cmd.exe prompt is a winner. After all this was only a ‘tip’ and not an attempt to promote using batch files in any way.
Outstanding the nitpickability of these folks. Raymond even added "I doubt anybody actually enjoys working with batch files…", meaning for those of use who *HAVE* to use batch files and cannot use anything else (locked-down PC, corporate standards, least common-denominator, etc. etc. etc.) then, as Raymond says, "doesn’t mean tips on using it more effectively aren’t valid."
Sheesh.
Looks like Raymond needs a nitpicker’s prelude to explain why he’s talking about what he’s talking about.
Ha! I used "tokens=*" instead of "delims=". And I use uppercase letters for the variable name, to make tilde expansions non-ambiguous. And you should prefix the "do" command with an @, or the command will be echoed. In other words, I’d use:
for /f "tokens=*" %%I in (‘dir /ad/s/b’) do @echo %%I
Also, how to perform an infinite loop: for /l %I in (1,0,1) do …
Finally a little warning: you can make a pipeline of "for" loops (and, indeed, any built-in command), but be aware that, if there are more than two in the same pipeline, each will be run in a subprocess. The /V and /E options won’t be passed onto the cmd.exe subprocess, I guess as a bug, and this might screw with !VARIABLE! expansion; in that case, you can sacrifice syntactic sugar by replacing the offending "for" loop with an explicit cmd /e:on /v:on /c "for …"
Back in the days of DOS, I used a little utility called "Sweep" (http://short.stop.home.att.net/freesoft/batch2.htm#sweep) that did the same thing.
For example, "sweep del *.bak" would delete *.bak files from the current directory and all subdirectories under it.
> I doubt anybody actually enjoys working with batch files
/me sheepishly raises hand…
http://channel9.msdn.com/ShowPost.aspx?PostID=51329
http://channel9.msdn.com/ShowPost.aspx?PostID=189460
My particular favorite has to be xargs.bat, which allows the charmingly anaOStic
dir /b /a:-d *.cpp | xargs start
or
dir /b /a:-d *.cpp | xargs /addquotes start ""
(to placate start’s weird argument syntax)
Which supposes one already went through the bureaucracy to gain approval for installing software domain-wide
Adam, I won’t go over how wrong your post as a whole is, but the quote you use stands out. I believe the meaning is that if you give people too much time for a task they’ll waste time on things that don’t actually help with the task.
If you have someone who has unlimited free time because they have no job and don’t have to pay rent or buy food an acceptable solution might be to create a new programming language, build a community, and have the community come up with tools to solve their problem. People who have limited time have to devote all of it to actually solving the problem, not configuring new platforms.
Steve Miller (creator of Dependency Walker) has a DOS toolbox application collection. One of these applications is global.exe, which let’s you run a command for each subdirectory with some additional options. See his applications page for more details:
http://www.stevemiller.net/apps/
Ah, batch files. I can never quite decide whether to feel nostalgic about them or just install PowerShell and say "good riddance". :P After spending a brief time (like, 30 minutes) with Exchange 2007 and PowerShell, the latter is more likely. :)
They are a good solution sometimes when you can’t go off installing new stuff, but WScript also fits that description and is a lot more flexible. Bottom line, unless what I need to do really is nothing more than a simple sequence of commands, I tend to not use batch files.
Anti-nitpickers corner: this isn’t to say the tips aren’t useful and/or you should stop giving them.
I love tips like this – I still have "which.bat" from one of the earlier tips posts, where people argued over which was the most elegant solution.
I admit I don’t yet see the appeal of the
"for /r /d %I in (.) do @echo %I"
over
for /f "delims=" %%i in (‘dir /ad/s/b’) do echo %%i
…but that just makes me look forward more to the "I’ll come back to this." post.
I notice very few people saying in the C posts "OMGWTFBBQ use Perl/Python/Java/Bash!" – why should this post be different? It’s a post about cmd commands, it’s blatantly obvious that there are alternatives out there, but that’s no more the point than in the C language posts.
"[If your machines aren’t already running Windows, then yes, you would have to install Windows, too, and that would be quite a burden. I guess I have to add a new sentence to the nitpicker’s corner now. -Raymond]"
No, it’s allright -_-‘ I was just kinda silly :p
One trick I liked in Dos batch files is that you can have functions, you just need to simulate them with recursion, e.g.
if "%1"=="/foo" goto foo
if "%1"=="/bar" goto bar
@rem call function foo
call %0 /foo fooargs
@rem call function bar
call %0 /bar barargs
goto exit
:foo
@echo foo – args %2
goto exit
:bar
@echo bar – args %2
goto exit
:exit
The idea of a language which forces you to do this is oddly charming.
Though it turns out that in Windows, you can actually do this
@rem call function foo
call :foo fooargs
@rem call function bar
call :bar barargs
goto :EOF
:foo
@echo foo – args %2
goto :EOF
:bar
@echo bar – args %2
goto :EOF
Call now allows you to call labels as :label, and :EOF is a built in end of file label. Now that’s progress ;-)
CMD.EXE’s "help" command is a riot. Somebody has carefully (and reasonably completely) documented all of the cute and fun bits of the script language. It just most people don’t know it’s there ("help" on DOS5/6 wasn’t wildly useful) and some of the more magically useful bits aren’t where you might expect (PUSHD creating temporary drive mappings for UNC paths, for example).
Raymond is rejecting cygwin not on technical basis. It’s because his employer doesn’t want him to appreciate other vendors applications.
I think Raymond wasn’t "rejecting" CYGWIN, but if you read the linked article "now you have two problems" href=http://blogs.msdn.com/oldnewthing/archive/2006/03/22/558007.aspx all will be clear.
I hope the link works.
Hey thanks for this. I don’t think I realized that you could specify no delims at all by using that option, when I wrote my last batch file. Time to go back and see if this simplifies things, it might well.
Not all corporate structures are completely hidebound. Installing something like perl shouldn’t be all that hard, given its long history and the rather minimal security risks of having it there when you aren’t using it.
Thanks for the tip! Another one I’ve found useful is enabling delayed environment variable expansions (cmd /V:on). That plus xcopy /D makes selectively deploying directory contents across a network onto an XPe target a cinch.
For nostalgia they’re stored in c:bin. The XP command shell may not be bash but it’s got quite a few hidden gems for the "not quite worth a program" level of automation.
Ooc, I really like Raymond’s intellectual honesty…if every guy at his workplace were like him there where no FUD against other OSes and Windows would be a better product.
End of Ooc,
Cheers,
Ema! ;-)
I didn’t receive Access with my copy of Office for XP so why did I receive a Microsoft Access security update? I removed Windows medea 6 security update so shouldn’t streams play just fine in other media players?
for
command? -Raymond]PingBack from http://www.synesthesia.co.uk/blog/archives/2007/05/14/links-106/