List all paths with a suffix in CMD - windows

I would like to get all the paths that ends with a given suffix (like 'example/subpath/string') . Is there any simple way of doing it in Windows cmd?

dir /ad /s /b c:\startingPoint | findstr /l /e /c:"example\subpath\string"
dir folders (/ad) from c:\startingPoint and below (/s) in bare format (/b). Filter the list with findstr, we only want the lines with the literal (/l) "example\subpath\string" (/c) at the end of the line (/e)
Adapt as needed

Related

Windows cmd: piping the dir list output into find (or findstr) is not working

I need to do some very big Windows searches for some specific searchterms in th contents of all the files in a folder and all sub-folders. The GUI search facility is not finding all my tests, so I would like to try to use find via the cmd.
I can list all filenames in raw data format using:-
dir /S /B
I can successfully search for the searchterm in thecontents of all files in a single folder using :-
find "Searchterm" *.*
But there are thousands of recursive sub-folders, so when I pipe the output from the dir listing to the find (and exclude the filename parameter):
dir /S /B | find "Searchterm"
I am getting no results.
Furthermore, I have also successfully sent all the dir /B /S filenames to a text file:-
dir /S /B >> filenames.txt
and using type to pipe the contents of each file from the list to the find :-
type filenames.txt | find "Searchstring"
This does not work either. What am I missing? Microsoft's documentation suggests exactly the same format in https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/find as I am trying.
The solution to your question(s) should be clear by reading the output from %SystemRoot%\System32\findstr.exe /? ENTERed in a Command Prompt window.
I'd advise that you use the /L, literal, option for your initial code.
Direct results example:
%SystemRoot%\System32\findstr.exe /I /L /P /S "Searchstring" *
If you first send the filenames to a text file, e.g. Dir /B /S /A:-D 2>NUL 1>"filenames.txt", you could use the following idea:
%SystemRoot%\System32\findstr.exe /F:"filenames.txt" /I /L /P "Searchstring"
Just be aware, in this case, that unless you include a path outside of the target tree when initially creating filenames.txt, it will include itself in its own content. That means your FindStr command will also pick up any matches in that file too.

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

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 ?
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:
C:\Temp\LocalState
C:\Temp\Development & Test(!)\LocalState
C:\Temp\Folder 2\LocalState
C:\Temp\"Local State"
C:\Temp\Development & Test(!)\"Local State"
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 with using a separate command process started in background.
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()

How to list the names of all the files and directories in a folder using for loop in a batch file

I want to list all the files and directories inside a directory using a for loop in a batch script. How can I do it?
I used below but it didn't work :
for /r %%I in (".") do ( ls -ltr '%%I') ## Listing only filenames and not directories name
Any help is appreciable.
Thanks!
If you just want a list of dirs and files, recursively, what about:
dir /b/s "."
If you want to do something special with each of the stream item, using a for loop, you could do something like:
for /f "tokens=* delims=" %%i in ('dir /b/s "."') do ( echo "%%i" )
There I used echo for echoing, but you can put whatever you need.
"to list all the files and directories inside a directory using a for loop in a batch script." you should use the DIR command.
If you open a Command Prompt window, type dir /? and press the ENTER key you should see its usage information.
One important thing to note is the /A option. What is not mentioned specifically is that using it alone, (without additional parameters D, R, H, A, S, I, L or O), enables all attributes.
Therefore to list all items in the current directory recursively in bare format you'd use:
DIR /A /B /S
or
DIR . /A /B /S
If you wanted to list them in a specific location relative to the current directory, you'd use:
DIR "Location" /A /B /S
or:
DIR ".\Location" /A /B /S
And For a specific absolute path:
DIR "L:\ocation" /A /B /S
And if you wanted it to be in the same location as the batch file itself, you can use the special variable for the current script %0:
DIR "%~dp0." /A /B /S
To perform that command within a For loop, you should first open a Command Prompt window, type for /? and press the ENTER key, to read its usage information.
You should note that you are running a command, and should therefore use a FOR /F loop, i.e.
FOR /F ["options"] %variable IN ('command') DO command [command-parameters]
But should also note that:
To use the FOR command in a batch program, specify %%variable instead of %variable.
So:
FOR /F ["options"] %%variable IN ('command') DO command [command-parameters]
As you have your command already, the options now become important. The first you need to understand is eol which whilst it seems to mean End Of Line, is specific to only one end, the beginning! What this does it does not pass any result of 'command' to the DO if it begins with a single specific character. The defualt for eol is the semicolon ;, (probably because historically it was a common line comment marker in many files). Generally, a file or directory name could include, and begin with a semicolon, so in order to include all files, you would specify a character which cannot be included in a filename, for me the simplest is ?, although I've seen many examples using |. However, when you perform a recursive DIR command, every returned line is a fully qualified path, none of which can begin with a semicolon, so you can for this task ignore eol. You clearly want everything returned, so do not require skip any lines returned. tokens and delimiters, are adjusted according to what you want to do with the results, in this case, you want the entire content of each line returned by your 'command' with no splitting on specific characters. You should note that tokens by default is 1 and delims by default is both the space and a horizontal tab characters. You should stipulate therefore that you do not want any delimiters, so that the first token is everything returned on each line of 'command'. You rarely require the usebackq option, so for the purposes of this answer, and your task, just ignore it.
Now put it all together:
FOR /F "delims=" %%G IN ('DIR "Location" /A /B /S') DO command
Finally you can use your wanted DO command with each result from your parenthesized DIR command. That result will be held within your variable %%G.
For the purposes of just viewing each result, we'll use the ECHO command, (you would just replace that with your chosen command). Please note that as each result of the DIR command is a file or directory name string, you should generally doublequote it.
allObjects.cmd
FOR /F "delims=" %%G IN ('DIR "Location" /A /B /S') DO ECHO "%%G"
Please remember to replace "Location" as needed, before running the Windows Command Script
Create two loops, one for files
for /r %%i in (*.*) do <something>
and one for directories
for /r %%i in (.) do <something>
and use the same command after do
But, since you have Cygwin installed anyway, why not use that power and do
find . | xargs -L1 ls -ltr
where find . finds all files and directories, | xargs passes the output to xargs which -L1 splits the output after each line and passes each line to ls -ltr.

Use Windows findstr to list files not containing a string

From Windows CMD I can use
findstr -m subroutine *.f90
to list all files with suffix .f90 containing "subroutine". To list all .f90 files not containing the string I can do something like
dir /b *.f90 > files.txt
findstr -m subroutine *.f90 > files_with_string.txt
and then write a script to list the lines in files.txt not found in files_with_string.txt. Is there a more elegant way?
There is a /v option in findstr, but that wouldn't help here.
Process each file with a for loop, try to find the string and if it doesn't find it (||), echo the filename:
for %a in (*.f90) do #findstr "subroutine" "%a" >nul || echo %a
(above is command line syntax. For use in a batchfile, use %%a instead of %a (all three occurences))
I needed to search for filenames which contained one specific string ("up"), but did not contain another string ("packages").
However, I was hoping to run it from the command line.
This is actually possible to do, you just have to call findstr twice.
Mine looked like:
dir /B /S up | findstr /I "up" | findstr /I /v "packages"
That means:
search all directories (/S & subdirs)
give me the bare formatting (/B)
and pass it through (| pipe) findstr (/I ignore case) to find ones that have "up" then
pass the results (| pipe) through findstr again but this time ignore all that
contain (/v) "packages"
If you have items like:
c:\test\packages\up
c:\extra\thing\up
c:\extra\thing\packages\up
c:\extra\test\up
c:\extra\test\nothing
The results would be only the ones that contain "up" but do not contain "packages"
c:\extra\thing\up
c:\extra\test\up
Call findstr /v multiple times on result
In other words you can keep passing the result into another findstr with /v to remove the ones that have additional words you don't want.

Is there a way to exclude certain values/variables from a wildcard in a for loop

for /d %%A IN (u:\mainfolder\*) DO if not exist "%%A\%var1%" mkdir "%%A\subfolder"
I want to exclude certain folders in the directory u:\mainfolder\ so that mkdir executes on all but a few of the folders there. Is there a way to exclude certain folders given the use of the wildcard?
If you only have 2 or 3 to exclude you can do something like this.
for /d %%A IN (u:\mainfolder\*) DO if /i not "%%A"=="u:\mainfolder\Name1ToExclude" if /i not "%%A"=="u:\mainfolder\Name2ToExclude" if not exist "%%A\%var1%" mkdir "%%A\subfolder"
Otherwise if you have more, you probably want to use a table of names to exclude.
The command FOR does not support an exclude option.
But the task can be achieved using the commands DIR and FINDSTR executed by FOR.
#echo off
set "MainFolder=U:\mainfolder"
for /F "delims=" %%A in ('dir "%MainFolder%\*" /AD /B ^| %SystemRoot%\System32\findstr.exe /E /I /L /V /X /C:"Exclude Folder 1" /C:ExcludeFolder2 /C:FolderToExclude3 2^>nul') do if not exist "%MainFolder%\%%A\%var1%" mkdir "%MainFolder%\%%A\subfolder"
set "MainFolder="
The command DIR is executed to output only directories in directory specified with environment variable MainFolder because of the options /AD (attribute directory) and /B (bare format). The directory names are output by DIR without path, just the directory names.
The output of DIR is piped as input to FINDSTR using redirection operator |.
FINDSTR searches in all lines for one of the strings specified with option /C as literal string because of option /L not enclosed in double quotes or enclosed in double quotes because of directory name contains a space character or one of these characters: &()[]{}^=;!'+,`~
The search is case-insensitive because of option /I.
A match is only positive if the enter line matches completely with a search string because of /X which means the entire directory name must match completely with one of the search strings.
The option /V results in an inverted output by FINDSTR. Instead of printing the lines matching with one of the search strings, it prints the lines (= directory names) not matching with any of the search strings.
The filtered directory names without path are processed line by line by FOR.
The redirection operators | and > must be escaped with caret character ^ in the finally executed command line:
dir "U:\mainfolder\*" /AD /B | C:\Windows\System32\findstr.exe /E /I /L /V /X /C:"Exclude Folder 1" /C:ExcludeFolder2 /C:FolderToExclude3 2>nul
This command line is executed by FOR with using a separate command process started in the background. The redirection operators | and > must be escaped with ^ to be interpreted as literal characters on parsing the entire FOR command line by Windows command interpreter before executing command FOR with the rest of the line.
On a longer list of directories to exclude I suggest to write the directory names into a plain text file and use option /G: of FINDSTR instead of specifying them all with /C: on command line.
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 /?
set /?
Read also the Microsoft article about Using Command Redirection Operators.

Resources