1

I have a variable %folder% which contains one or more directories like so c:\users,c:\windows,d:\ etc. I need to do a dir command into every directory in a way that allows multiple search terms found in %wildcards% variable like *.txt *.lst "*old*news*" etc. Here is my attempt

for /f "tokens=1,2,3,4,5,6,7,8,9,* delims=," %%a in ("%folders%") do (
    if not "%%~a"=="" dir %%~a\%wildcards% /s /b /a-d 2>nul >%files%
    if not "%%~b"=="" dir %%~b\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~c"=="" dir %%~c\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~d"=="" dir %%~d\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~e"=="" dir %%~e\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~f"=="" dir %%~f\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~g"=="" dir %%~g\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~h"=="" dir %%~h\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~i"=="" dir %%~i\%wildcards% /s /b /a-d 2>nul >>%files%
    if not "%%~j"=="" dir %%~j\%wildcards% /s /b /a-d 2>nul >>%files%
)

It fails with multiple wildcards. I guess this would work if I entered each directory so that no directory is required with the dir commands, but the whole thing is already getting so convoluted I must be missing a simpler way of doing this?

[edit removed]

Bricktop
  • 533
  • 3
  • 22
  • `Dir /s /a C:\Users\*.txt C:\Users\*.doc C:\Windows\*.txt C:\Windows\*.exe` Line length is > 4000. –  Dec 18 '19 at 20:41
  • 3
    If the folders do not contain spaces or other token separators (like `;`, `=`) nor special characters (like `%`, `^`, `(`, `)`), or such are quoted, you could use `(for %%I in (%folder%) do pushd "%%~I" && (dir /S /B /A:-D %wildcards% 2> nul & popd)) > "%files%"`... – aschipfl Dec 18 '19 at 20:44
  • @Mark I would have to divide `%wildcards%` into separate variables, and run every one in combination with every dir in `%folders%`, right? – Bricktop Dec 18 '19 at 20:46
  • @aschipfl why does that begin with a `(` block? I didn't know you can do that. – Bricktop Dec 18 '19 at 21:33
  • 3
    The whole `for` loop is put in between parentheses, so the redirection `> "%files%"` happens once only (which is faster than doing `>>` in the loop body multiple times); when removing the parentheses, the `>` is part of the loop body... – aschipfl Dec 18 '19 at 21:51
  • 1
    Not sure if it would have been better to have asked a new question rather than have edited this one. Anyway, echoing is enough, but you should use `echo(%%f` instead. I believe there are simply no matches. Would you please provide the content of `%whitelist%`? – aschipfl Dec 23 '19 at 07:04
  • @aschipfl I have been trying with `%whitelist%` content `none` – Bricktop Dec 23 '19 at 11:09
  • 1
    The major difference I can see is that you're running two recursive commands, one nested within the other. If the outer recursive directory listing picks up `directory1` and within that there are subdirectories, your inner recursive file search will list every file within that branch, including those subdirectories. Once done, the recursive outer loop will drop into one of the subdirectories, you've already parsed and list the same files. And absolutely, this question should not have been edited after having accepted the answer. Few people will click on already accepted answers, to answer them – Compo Dec 23 '19 at 17:02

1 Answers1

2

If, and only if, the directory paths/names:

  • do not contain commas , on their own,
  • and if they are unquoted:
    • do not contain other token separators, like SPACE, ;, =,
    • do not contain other special characters, like ^, &, (, ),

You could use a standard for loop that iterates through all directories, because the comma , is a token separator just like the SPACE:

rem // Redirect to output file once in order to avoid multiple file I/O operations:
> "%files%" (
    rem // Iterate through all directory paths in the comma-separated list:
    for %%I in (%folder%) do (
        rem // Change into currently iterated directory:
        pushd "%%~I" && (
            rem // Use the `dir` command so that the wildcards relate to the current directory:
            2> nul dir /S /B /A:-D %wildcards%
            rem // Return to former working directory:
            popd
        )
    )
)

If the directory paths/names may contain token separators other than , and/or other special characters but are not quoted, you could do this to prepare the directory list in advance:

rem // Optionally remove quotation marks, just in case:
set "folder=%folder:"=%
rem // Put quotation marks around every comma-separated item:
set "folder="%folder:,=","%""

If the directory paths/names may even contain commas on their own (which requires such to be quoted in order to distinguish between the separation commas) things become much more complicated; you may want to take a look at this post, where such a situation is handled (with ; as the separator).

aschipfl
  • 33,626
  • 12
  • 54
  • 99