I'm trying to list out file names excluding their extension,
How I want it:
File1
File2
File3
How it currently is:
File1.txt
File2.txt
File3.txt
I tried using
#echo off
dir /A:-D /B
pause
but it isn't working. I tried it in both a batch file and in command prompt.
Am I using the right command?
Use FOR and ECHO to achieve this
For example, assuming the extension is always .txt:
for %f in ("*.txt") do #echo %~nf
Instead of using DIR, we are using the FOR command to go through the list and sending each one to ECHO, with the "~n" option inserted into the %f, to cause the extension to be not shown.
An alternative is
FORFILES /c "cmd /c echo #fname"
However with this I get quotation marks around each output filename, which isn't what you want.
If running inside a batch file, you need to double the %'s for variables
for %%f in ("*.txt") do #echo %%~nf
If you need to handle multiple file extensions
As long the directory doesn't contain any subdirectories whose names have an extension, you can generalise the *.txt to *.*:
for %f in ("*.*") do #echo %~nf
If you may have some filenames with only an extension
Where the file has an extension but nothing before it, e.g. .gitignore, the resulting empty ECHO command will output an inane message, such as ECHO is on. To avoid this ruining your onward plans, you can filter out lines containing ECHO is, with the FIND command and the /V option:
for %f in ("*.*") do #echo %~nf | find /v "ECHO is"
If your local language causes DOS to output something other than ECHO is then this filtering will not work. And it will miss any file that happens to contain ECHO is in the filename.
To search subdirectories too, add '/R' to the 'for'
for /R %f in ("*.png") do #echo %~nf | find /v "ECHO is"
Conclusion
This is all crazy, of course, but this is the agonising price we pay for using Batch language instead of an actual sensible language. I am like an alcoholic, promising to all and sundry that I will never write a line of Batch code again, and then finding myself coming back to do so again, sheepishly.
It'll be much easier in PowerShell
(Get-ChildItem -File).BaseName
or
Get-ChildItem | ForEach-Object { $_.BaseName }
Get-ChildItem can be replaced with the aliases ls, gci or dir and ForEach-Object can be replaced with %
So from cmd you can run either of these to achieve the purpose
powershell -Com "(ls -File).BaseName"
powershell -C (ls^ -File).BaseName
powershell (ls^ -af).BaseName
To add to Eureka's answer, the vanilla dir command cannot achieve what you're looking for.
C:\Users\jacob>dir /?
Displays a list of files and subdirectories in a directory.
DIR [drive:][path][filename] [/A[[:]attributes]] [/B] [/C] [/D] [/L] [/N]
[/O[[:]sortorder]] [/P] [/Q] [/R] [/S] [/T[[:]timefield]] [/W] [/X] [/4]
[drive:][path][filename]
Specifies drive, directory, and/or files to list.
/A Displays files with specified attributes.
attributes D Directories R Read-only files
H Hidden files A Files ready for archiving
S System files I Not content indexed files
L Reparse Points - Prefix meaning not
/B Uses bare format (no heading information or summary).
/C Display the thousand separator in file sizes. This is the
default. Use /-C to disable display of separator.
/D Same as wide but files are list sorted by column.
/L Uses lowercase.
/N New long list format where filenames are on the far right.
/O List by files in sorted order.
sortorder N By name (alphabetic) S By size (smallest first)
E By extension (alphabetic) D By date/time (oldest first)
G Group directories first - Prefix to reverse order
/P Pauses after each screenful of information.
/Q Display the owner of the file.
/R Display alternate data streams of the file.
/S Displays files in specified directory and all subdirectories.
/T Controls which time field displayed or used for sorting
timefield C Creation
A Last Access
W Last Written
/W Uses wide list format.
/X This displays the short names generated for non-8dot3 file
names. The format is that of /N with the short name inserted
before the long name. If no short name is present, blanks are
displayed in its place.
/4 Displays four-digit years
Switches may be preset in the DIRCMD environment variable. Override
preset switches by prefixing any switch with - (hyphen)--for example, /-W.
Additionally, as an alternative to the suggestion to use ("*.txt"), if your file list includes multiple extensions you might either exclude different extensions or use *.* to get all files with a . in the name. Play around with that glob to get what you want out of it.
This is possible with a dir command and a for loop:
#echo off
for /F "delims= eol=" %%A IN ('dir /A-D /B') do echo %%~nA
If you want the full path without the extension, try:
#echo off
for /F "delims= eol=" %%A IN ('dir /A-D /B') do echo %%~dpnA
For cmd one-line:
for /F "delims= eol=" %A IN ('dir /A-D /B') do echo %~nA
And for the full path without the extension, try:
for /F "delims= eol=" %A IN ('dir /A-D /B') do echo %~dpnA
These small programs, loop through all the files in the folder except directories, and echo only the filenames/full paths without the extension.
dir -Name -File
This is for PowerShell
Related
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.
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()
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.
I have a lot of internal HDDs, with video files spread a bit all over the place.
I would like to be able to list all the video files (*.avi *.mp4 *.wmv...) in DIRs and SUBDIRs, while also excluding some folders from the listing, and outputting the results to a file.
I have tried using:
dir "D:\Mini Clips Series" *.avi *.mp4 *.wmv /b /s /a-d >> E:\Temp\List.txt
and variants thereof. The main problem being that specifying several file types doesn't seem to be compatible with the /s switch...
Many thanks in advance.
You can use a for loop with the /R (recurse) switch, passing your extensions as a set.
for /R "D:\Mini Clips Series" %i in (*.avi *.mp4 *.wav) do dir /b %i >> "E:\Temp\List.txt"
The /R switch recurses sub folders as well, so you don't need the /s on the dir command, as you can see. (I didn't bother with the /a-d, but you should still be able to use it.)
If there's an existing "E:\Temp\List.txt", you'll want to delete it first, as the above will append to (not overwrite) that file (the >> redirection instead of >). If you don't want to have to do that, you can use this instead:
del "E:\Temp\List.txt" & for /R "D:\Mini Clips Series" %i in (*.avi *.mp4 *.wav) do dir /b %i >> "E:\Temp\List.txt"
The & allows both commands to be on the same command line. The del is done first, followed by the for loop.
You can find out more about the for command by typing for / from a command prompt.
Well after a few tries, finally found a batch script that works under Win7.
#ECHO OFF
SET test="D:\Mini Clips Series"
FOR /R %test% %%F IN (*.avi *.mp4 *.wmv) DO (
ECHO %%F >> List.txt)
It outputs all corresponding filenames with their full path (similar to dir /b /a-d), recursively (/s).
Thanks again for the helpful replies.
Have you considered using Grep? There are various Windows binaries for it and you could off-load the filtering from 'dir' to grep.
dir "folder" /S | grep "regex" > list.txt
Been working on a systematic file search script to retrieve the name of all documents in a directory, and all sub directories that contain a determined search string. Essentially, it will log the search results. It would be nice to have it also search the file names, but that's not yet important.
Code:
#echo off
echo - Will search all files in current directory, and subdirectories.
echo - Will ignore case sensitivity.
echo - Will only search for term within readable documents.
set /p searchfilter=Search Filter:
set results=%CD%\results.txt
echo Searching...
echo Results: > "%results%"
for /f "usebackq tokens=*" %%i in (`dir /s/b/A:-D/o:e`) do (
find /i "%searchfilter%" "%%~nxi" >nul && echo %%~nxi >> "%results%"
)
echo Search complete.
pause
Run-down: System requests a string from the user. Then, the system saves a handle to the results file (thought that would fix the problem, didn't). The system then filters all files, excluding folders, from the directory, and sub directories, printing the bare name of the file (with extension), where it will proceed to scan each file for the search string, and save any positive search results to the text file.
It seems on a number of files, I receive a "File not found - " error, and need help identifying it. My guess, is that it has something to do with trying to find a sub directory file without the directory handle.
find /i "%searchfilter%" "%%i" >nul && echo %%~nxi >> "%results%"
should fix your problem, as you've flagged yourself. If you are searching for a file named fred.txt that exists in a subdirectory but mot in the root of the subtree scanned, then you'll get a File not found error.
Your choice whether you echo just the name and extension to results or whether you echo the full filename, of course. Personally, I'd use `%%i and get the whole thing.
I'd also change
for /f "usebackq tokens=*" %%i in (`dir /s/b/A:-D/o:e`) do (
to
for /f "delims=" %%i in ('dir /s/b/A:-D/o:e') do (
but that's just a matter of style in this case.
This should give you a tool to search filenames in the current folder tree and log the results to a file - in c:\path\file.ext format.
Replace searchstring with your search term and remove *.doc if you want to search all files, or replace it with *.doc *.txt *.ini *.src if you want to filter a number of filetypes.
#echo off
dir /b /s /a-d *.doc |findstr /r /i ".*\\.*searchstring.*" >results.txt