views:

4246

answers:

6

Another question from an long-time Unix/Linux user who finds himself in a Windows world. First let me explain exactly what I'm trying to do. I'm using the Windows cmd.exe shell, and I want to list all directories below the current directory that contain a bin\Debug hierarchy, and determine if they contain any files (e.g.: trying to figure out if my NAnt clean target is working properly). My hierarchy might look something like this:

\Current
    \DirA
         \bin
             \Debug
                  (some files under debug)
             \Release
    \DirB
         \bin
             \Debug
    \DirC
         \bin
             \Release

In Unix, ls */bin/Debug would just give me a list of all the stuff in DirA/bin/Debug, and show me the fact that DirB/bin/Debug is empty. I've tried different contortions in the cmd shell, but keep winding up with stuff like:

    > dir *\bin\Debug
    The filename, directory name, or volume label syntax is incorrect.

    > dir *\*\*
    The filename, directory name, or volume label syntax is incorrect.

Is there something subtle I don't understand about the dir command, or is it just limited that way?

Yes, I realize I can just switch to explorer, navigate, right-click, and probably eventually craft a search that does what I want, but I'm more interested in the quick-n-dirty command-line solution.

+3  A: 

Windows doesn't do wildcards the way Linux does. Only the filename portion can contain wildcards.

You can download a version of ls that runs on Windows and use that. I've used Cygwin, but I'm sure there are others.

Mark Ransom
Also PowerShell
Joel Coehoorn
Another thing to keep in mind: in Windows wildcards are expanded by the command, not by the shell.
Laurence Gonsalves
+2  A: 

unxutils has an ls command. The problem is really with the windows shell, however. On unix your shell will expand */bin/Debug into the relevant pathnames and feed them to the ls command as separate command-line arguments.

Cygwin would certainly do the trick for you, or you could try a windows port of a unix shell such as bash. If you wanted to go the scripting route, you could code up something in python pretty easily using the glob module, and most other scripting languages have an equivalent.

Tim Gilbert
A: 

In the Windows world cmd.exe does not expand wildcards - they get passed as-is to the program in its command line or argv array. Therefore each program parses and expands them differently, and some of the more advanced uses (like you're looking for) are generally not supported.

timgilbert's suggestion of using Cygwin is a good one, also the GNUWin32 package might have something that'll help you out.

Michael Burr
+1  A: 

You can do something like "dir /s *.obj *lib". It'll give a summary at the end of how many files matched.

Joel Lucsy
Close. I gave you props, but James' answer is closer, as it filters out the files *not* under \debug for me.
Ogre Psalm33
+2  A: 

Something like this should do what you want. At the root directory of the project type:


c:\path\to\slndir>dir *.dll *.exe /s /b | findstr /i "bin\debug"

Dir arguments: /s - recursive, /b - "bare", no extra info
findstr arguments: /i - ignore case

In general, 'help command' will show help for the shell commands. If that doesn't work, then
'command /?' will generally show help.

james
Excellent! I realize there are many tools/toolkits out there to help me "linuxize" my Windows, but I was looking for the Windows way to do what I'm trying to do, and this is it exactly!
Ogre Psalm33
+1  A: 
@for /D /r %P in (.) do @for %Q in ("%~fP\bin\Debug\*") do @echo %~ftzaQ

Not nice, but should work. You may also put into a .cmd file (then replace every single % into double %%). Or define a macro using doskey (yes, it still exists).

Ensure that cmd extensions are enabled.

EDIT: How it works:

The first for loop iterates through all subdirectories (/D and /r switch) iteratively. %~fP expands to the full path of that directory. Then, it appends \bin\Debug* to that path. The second for loop enumerates all files that match. %~ftzaQ is expanded to every file match and printed to the screen by echo. The strange %~ftzaQ formats it like a dir output. The @ character avoids that the commands itself are printed on the screen.

For more, see

Meinersbur
I tried this and indeed it does work. But being somewhat inexperienced in the cmd shell, I don't quite understand it all yet :-).
Ogre Psalm33