Home > Mobile >  Recursively search for folder whose name may contain space(s), in a specific directory
Recursively search for folder whose name may contain space(s), in a specific directory

Time:03-29

As said in Q-title, I am trying to find a particular directory called Local State, but it could be spelled by some Apps as LocalState or Local State, anyone of which is surely present in every Apps' folder inside %USERPROFILE%, which I am trying to list out.

Now for that I had to write two lines, one for finding LocalState which works well, and it's as given:

pushd "%USERPROFILE%"
for /d /r %%h in (LocalState) do if exist "%%h" echo "%%h"
popd

But with the almost same line when I try to find Local State folder it doesn't show the paths as expected, as it adds extra quotes around the searched folder. See this:

pushd "%USERPROFILE%"
for /d /r %%h in ("Local State") do if exist "%%h" echo "%%h"
popd

gives this, which is weird, as any action can't be taken on this extra quoted path:

....
....
"C:\Users\<Username>\AppData\Local\BraveSoftware\Brave-Browser\User Data\"Local State""
"C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\"Local State""
....
....

Now I am wondering is it possible with one line only I am able to search folder name like LocalState or Local State in the specified folder with batch script ? Something like this?

for /d /r %%h in ("Local? State") do if exist "%%h" echo "%%h"

And it would show paths in regular proper quoted format like:?

....
    ....
    "C:\Users\<Username>\AppData\Local\BraveSoftware\Brave-Browser\User Data\Local State"
    "C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\Local State"
    ....
    ....

Or if that's not at all possible, then how can I find folder names with spaces and echo those paths in proper quoted format with no extra, unrequired quotes ?

CodePudding user response:

Why do the FOR command lines not work as expected?

The strings LocalState and "Local State" are not interpreted by for as folder name to search for because of neither containing * nor ?. The command FOR searches only for non-hidden files or with option /D for non-hidden folders on specifying a wildcard pattern.

There was tried:

for /d /r %%h in (LocalState) do if exist "%%h" echo "%%h"
for /d /r %%h in ("Local State") do if exist "%%h" echo "%%h"

The command lines above result in searching recursively for directories (including hidden ones) and assign to the loop variable h each found directory with full path not enclosed in " concatenated with the specified string LocalState or "Local State".

Example: The current directory is C:\Temp with following directory structure:

  • C:\Temp
    • Development & Test(!)
    • Folder 2

The IF condition is executed with following strings assigned to loop variable h:

  1. C:\Temp\LocalState
  2. C:\Temp\Development & Test(!)\LocalState
  3. C:\Temp\Folder 2\LocalState
  4. C:\Temp\"Local State"
  5. C:\Temp\Development & Test(!)\"Local State"
  6. C:\Temp\Folder 2\"Local State"

The directory names 4 to 6 are problematic on as they contain themselves two double quotes resulting in executing the IF conditions with not correct specified names for file system entries – directory or file or reparse point – that makes no difference for IF in this case with no backslash at end.

Somebody might think this behavior of FOR does not make sense, but that behavior is useful in some use cases, for example on creation of a file with a specific name in each folder of a directory tree.

The problem here is that there cannot be added * at beginning or at end, i.e. use *LocalState or "Local State*" because of that can result in false positives. FOR would really search now for non-hidden directories of which name ends with LocalState or starts with Local State.

So the usage of the following command line would not be good:

for /d /r %%h in (*LocalState "Local State*") do echo "%%h"

What are possible solutions?

A very fast possible solution is:

for /F "delims=" %%h in ('dir "%USERPROFILE%\LocalState" "%USERPROFILE%\Local State" /AD /B /S 2^>nul') do echo "%%h"

There is started in background one more cmd.exe with option /c and the specified command line within ' appended as additional arguments.

DIR searches first

  • for just directories because of option /AD
  • with the name LocalState or the name Local State
  • in the specified directory %USERPROFILE% and
  • all its subdirectories because of option /S and
  • outputs just the fully qualified directory name because of the options /B (bare format) and /S.

DIR is so smart to search in each directory for both directories names. So the entire directory tree is searched by DIR only once for both directory names at the same time.

The started cmd.exe closes itself once DIR finished.

The cmd.exe instance processing the batch file captures all fully qualified folder names output by DIR and FOR processes them now line by line.

The FOR option delims= defines an empty list of delimiters to turn off the default line splitting behavior on normal spaces and horizontal tabs. That is required because of each folder name should be assigned completely one after the other to the loop variable h for further processing and not just the part up to first space character in a full folder name.

Other solutions are:

for /F "delims=" %%h in ('dir "%USERPROFILE%\Local*State" /AD /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /E /I /L /C:LocalState /C:"Local State"') do echo "%%h"
for /F "delims=" %%h in ('dir "%USERPROFILE%\Local*State" /AD /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /E /I /R /C:"Local *State"') do echo "%%h"

DIR searches in both cases for directories of which name starts with Local and ends with State (case-insensitive) recursively in specified folder %USERPROFILE%.

There is used FINDSTR on the first command line to filter out all false positive found directories of which fully qualified directory name does not end with the case-insensitive and literally interpreted string LocalState or Local State like Local & State.

There is used FINDSTR on the second command line to filter out all false positive found directories of which fully qualified directory name is at end not matched by the case-insensitive interpreted regular expression Local *State which matches LocalState and Local State and also Local State (two spaces) because of * is interpreted here as preceding character (the space) zero or more times. Please notice the difference. In a wildcard pattern * means any character zero or more times, but not here in the regular expression search string interpreted by FINDSTR where it means preceding character zero or more times.

The two solutions searching with DIR for the directories with a wildcard pattern and using FINDSTR to filter out false positive found directories are a bit slower than the solution using just DIR with the two directory names to search for.

In all provided solutions could be modified the DIR option /AD to /AD-L to ignore junctions and symbolic directory links (reparse points) and find just real directories.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • dir /?
  • echo /?
  • findstr /?
  • for /?

Read the Microsoft documentation about Using command redirection operators for an explanation of 2>nul and |. The redirection operators > and | must be escaped with caret character ^ on the FOR command lines to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded command line in a separate command process started in background.

CodePudding user response:

This will work in a batch-file run under cmd on windows.

FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
    "(Get-ChildItem -Recurse -Directory -Filter 'Local*State').FullName"') DO (ECHO Directory name is %%~A)

Requires PowerShell 5.1 or later. Find your version with the command $PSVersionTable.PSVersion.ToString() or (Get-Host).Version.ToString()

  • Related