When I use the dir command with folders ordered 1-100 or more, this is the result:
1
100
101
...
2
200
201
...
Because of this I have to scroll/look down to see the other numbers. And no, I'm not gonna rename them to 001, 002 [...] 057, etc.
How do I order the numbers correctly within the dir command without using for or any others?
You may not like it, and it may not be the quickest of methods, but it's certainly simple, despite the fact you requested not to use for:
For /L %G In (1,1,999) Do #Dir /B /A:D | %SystemRoot%\System32\findstr.exe /X "%G"
Or the lazier, (not recommended), route:
for /l %g in (1 1 999)do #dir/b/ad|findstr/x %g
Without the for loop you'd need to get a little more creative, but I suppose technically the findstr utility would be classed as 'others' and also excluded in your question:
Example using simple command joining:
Dir /B /A:D /O:N "?" | %SystemRoot%\System32\findstr.exe /R /X /C:"[123456789]" & Dir /B /A:D /O:N "??" | %SystemRoot%\System32\findstr.exe /R /X /C:"[123456789][0123456789]" & Dir /B /A:D /O:N "???" | %SystemRoot%\System32\findstr.exe /R /X /C:"[123456789][0123456789][0123456789]"
And, of course the lazier, (not recommended), route:
dir/b/ad/on ?|findstr/rxc:[1-9]&dir/b/ad/on ??|findstr/rxc:[1-9][0-9]&dir/b/ad/on ???|findstr/rxc:[1-9][0-9][0-9]
If neither of the above ideas are acceptable due to your exclusions of 'for' and 'others', then the answer is simple. It cannot be done.
Related
I don't understand why findstr doesn't work as I want.
I have the following files in my test directory:
aaa.jpg
bbb.png
ccc.svg
aaa_s.jpg
bbb_s.png
ccc_s.svg
aaa_small.jpg
bbb_small.png
ccc_small.svg
And I have the following line to pass directly to cmd.exe:
for /f "delims=" %f in ('dir /b /a:-d ^| findstr /ile "gif jpg png svg" ^| findstr /ie "_s.*"') do echo "%f"
To my opinion, it should match the following files:
aaa_s.jpg
bbb_s.png
ccc_s.svg
However, it's actually matches
aaa_s.jpg
bbb_s.png
ccc_s.svg
aaa_small.jpg
bbb_small.png
ccc_small.svg
What I'm doing wrong?
. is a FindStr wildcard for any character, and * is for zero or more occurrences of the previous character. So obviously _s.* matches _s followed by any character zero or more times; which covers _sm.
Please open a Command Prompt window, type findstr /?, press the 'enter' key, and read the usage information.
BTW, what's wrong with using:
Dir /B /A:-D *_s.*
If needs be you could pipe that to FindStr with /I /L /E ".gif .jpg .png .svg" for example:
Dir /B /A:-D *_s.* | FindStr /I /L /E ".gif .jpg .png .svg"
Alternatively you could include multiple matches to your Dir command and forget about using FindStr entirely:
Dir /B /A:-D "*_s.gif" "*_s.jpg" "*_s.png" "*_s.svg"
I am trying to show just the folders in a directory.
Example C:/Test/Game1.
In Game1 there are folders folder1, folder2, folder3. But there are more folders in folder 1, 2 and 3 which I don't want to show.
I have used -maxdepth 1 but it shows up with the error
Too many parameters - 1
The Windows tree command does unfortunately not support an option for the maximum depth. However, you could filder the output by the findstr command in the following way:
tree "C:\Test\Game1" /A | findstr /V /B /R /C:"[| ] "
Assuming that the output of this tree command is something like (using ASCII characters (/A) rather than extended ones, because they are easier to handle as they do not depend on the current code page):
Folder PATH listing for volume &&&&
Volume serial number is ####-####
C:\TEST\GAME1
+---folder1
| +---folder11
| | +---folder111
| | \---folder112
| \---folder12
| +---folder111
| \---folder112
+---folder2
| +---folder21
| \---folder22
\---folder3
+---folder31
\---folder32
The findstr command removes (/V) everything that begins (/B) with | or SPACE and is followed by three more SPACEs. These criteria are fulfilled for all lines that show a folder that is deeper then level 1. Hence the output would be something like this:
Folder PATH listing for volume &&&&
Volume serial number is ####-####
C:\TEST\GAME1
+---folder1
+---folder2
\---folder3
To display more levels, simply extend the search expression accordingly; so to go down until level 2, use /C:"[| ] [| ] ".
To hide the header (containing the volume information and the upper-case root path), just append a SPACE and /C:"[^+|\\]" to the command line.
Note that the Windows path separator is \ but not /.
So, what you wanted was to print all directories in a folder in a tree format (ASCII characters of course). Inspired from aschipfl's solution, I came up with the opposite one:
tree /A "C:\Test\Game1" | findstr /BRC:"[^| ] "
which actually echoes lines that don't contain string |.
For a more difficult/complicated solution, I came up with:
#echo off
set "counter=0"
cd /D "C:\Test\Game1"
echo FOLDER PATH listing
for /F "skip=1 tokens=*" %%A IN ('vol') do echo %%A
echo C:.
for /F "delims= eol=" %%B IN ('dir /B /AD') do set /a "counter+=1"
set "_counter=0"
setlocal EnableDelayedExpansion
for /F "delims=" %%C IN ('dir /B /AD') do set /a "_counter+=1" & if not !_counter! EQU %counter% (echo +---%%C) else (echo \---%%C)
pause
exit /b 0
But that is not a good solution at all: it just copies the way tree command works. Better use my first solution.
C:\Test\Game1" /A |findstr/V /B /R /C:"[| ] "
Just looking for lines that start with '+-' works on my machine.
tree /A "C:\src" | findstr /BR "[+\\]-"
Of course, there are other commands that can do this without tree.
cmd.exe - DIR /A:D
powershell.exe - Get-ChildItem -Directory -Recurse -Depth 0
I'm trying to list non-symbolic links in an specific directory and then delete them.
non-symbolic links definition: any file besides the ones that have been created using the command MKLINK /H
To identify those non-symbolic links I used the following approach:
#> fsutil hardlink list %file% | find /c /v ""
When the specified %file% is a symbolic link it returns a number bigger than 1, when it is just a simple file, it returns 1. So far so good!
My problem starts when I need to automate this process and get such return to compare if it is bigger than 1
That's is the code I'm trying to get running property:
#echo off
set some_dir=C:\TEMP\
for /f %%a in ('dir /b %some_dir%') do (
set count=fsutil hardlink list %%a | find /c /v ""
if %count% -EQU 1 del /Q %%a
)
Would someone explain me how such attribution and comparison on %count% variable could be done, please?
I'm trying to list non-symbolic links in an specific directory and then delete them.
There are some issues with your code.
for /f %%a in ('dir /b %some_dir%') do (
The dir /b doesn't work because it doesn't return a file name with a complete path (which is required as input for fsutil)
Use dir /b /s instead.
set count=fsutil hardlink list %%a | find /c /v ""
This doesn't set count to anything sensible.
Use another for /f and parse the output of fsutil so you can set a variable.
if %count% -EQU 1 del /Q %%a
This has two mistakes. You need to use delayed expansion to evaluate count correctly. Replace %count% with !count!. Also remove the -. Replace -EQU with EQU.
Try the following batch file.
test.cmd:
#echo off
setlocal enabledelayedexpansion
set some_dir=C:\TEMP\
for /f %%a in ('dir /b /s %some_dir%') do (
for /f %%b in ('fsutil hardlink list %%a ^| find /c /v ""') do (
set count=%%b
if !count! EQU 1 echo del /Q %%a
)
)
endlocal
Notes:
Remove the echo when you happy with what the result will be.
Example usage and output:
I have used f:\test\folder1 as my test directory. hard is a hardlink to 1.txt.
F:\test>dir f:\test\folder1
Volume in drive F is Expansion
Volume Serial Number is 3656-BB63
Directory of f:\test\folder1
29/08/2016 21:40 <DIR> .
29/08/2016 21:40 <DIR> ..
21/08/2016 09:46 0 1.txt
21/08/2016 09:46 0 2.txt
21/08/2016 09:46 0 3.txt
21/08/2016 09:46 0 4.txt
21/08/2016 09:46 0 5.txt
29/08/2016 21:38 <SYMLINK> file [f:\d]
21/08/2016 09:46 0 hard
29/08/2016 21:38 <SYMLINKD> test [f:\d]
7 File(s) 0 bytes
3 Dir(s) 1,764,846,960,640 bytes free
F:\test>test
del /Q f:\test\folder1\2.txt
del /Q f:\test\folder1\3.txt
del /Q f:\test\folder1\4.txt
del /Q f:\test\folder1\5.txt
del /Q f:\test\folder1\file
del /Q f:\test\folder1\test
Further Reading
An A-Z Index of the Windows CMD command line - An excellent reference for all things Windows cmd line related.
dir - Display a list of files and subfolders.
enabledelayedexpansion - Delayed Expansion will cause variables to be expanded at execution time rather than at parse time.
for /f - Loop command against the results of another command.
There are some problems in your code:
you need delayed expansion because you are setting (writing) and expanding (reading) the variable count within the same parenthesised block of code (namely the for /F %%a loop);
in your for /F %%a loop you need to state options "eol=| delims=" in order not to run into trouble with files whose names begin with ; (such would be ignored due to the default eol=; option) and those which have white-spaces in their names (you would receive only the postion before the first white-space because of the default delims SPACE and TAB and the default option tokens=1 (see for /? for details about that);
dir /B returns file names only, so %%a actually points to files in the current directory rather than to C:\TEMP\; to fix that, simply change to that directory first by cd;
to capture the output of a command (line) and assign it to a variable, use another for /F loop and set; this loop is going to iterate once only, because find /C returns only a single line; note the escaped pipe ^| below, which is required to not execute it immediately;
there is no comparison operator -EQU, you need to remove the - to check for equality;
it is a good idea to use the quoted set syntax as it is most robust against poisonous characters;
file and directory paths should generally be quoted since they might contain token delimiters or other poisonous characters;
Here is the fixed script:
#echo off
setlocal EnableDelayedExpansion
pushd "C:\TEMP\" || exit /B 1
for /F "eol=| delims=" %%a in ('dir /B "."') do (
for /F %%b in ('
fsutil hardlink list "%%a" ^| find /C /V ""
') do (
set "count=%%b"
)
if !count! EQU 1 del "%%a"
)
popd
endlocal
This can even be simplified:
#echo off
pushd "C:\TEMP\" || exit /B 1
for /F "eol=| delims=" %%a in ('dir /B "."') do (
for /F %%b in ('
fsutil hardlink list "%%a" ^| find /C /V ""
') do (
if %%b EQU 1 del "%%a"
)
)
popd
Since the inner for /F loop iterates always once only, we can move the if query inside, thus avoiding the definition of an auxiliary variable which is the only one we needed delayed expansion for.
Simplified method:
#Echo Off
PushD X:\YourDirectory
For %%a In (*.*) Do (
FSUtil HardLink List %%a|FindStr/VIC:"%%~pnxa">Nul||(Echo=Del "%%~a"))
Pause
When you're satisfied with the output Remove line 5 and also 'Echo=' from line 4
I'm new to Windows batch programming and to Stack Overflow, so please forgive me if I ask anything that's blatantly obvious to you seasoned, talented folks. I'm using Windows batch (.bat) to find files containing a certain string using findstr. However, I'm trying to skip certain folders within a directory.
setlocal EnableDelayedExpansion
set basedir=C:\folder
for /f %%g in ('dir /a:-h /b %basedir% ^| findstr /v "Projects" ^| findstr /v "Archive"') do (
findstr /i /m /s /c:"request" %basedir%\%%g *.* > %basedir%\Projects\list.txt
)
When I look in list.txt, the file output from findstr, I find that the folders I told it not to search were searched. That is, the output looks like this:
C:\folder\somefile.rtf
C:\folder\Requests\anotherfile.rtf
C:\folder\Projects\dontsearchme.txt
C:\folder\Archive\dontsearchmeeither.txt
C:\folder\Archive\Projects\dontsearchme.txt
If it had worked correctly, only C:\folder\somefile.rtf and C:\folder\Requests\anotherfile.rtf would have been included in list.txt. To test the looping code, I used the following:
setlocal EnableDelayedExpansion
set basedir=C:\folder
for /f %%g in ('dir /a:-h /b %basedir% ^| findstr /v "Projects" ^| findstr /v "Archive"') do (
echo %basedir%\%%g
)
That code works as desired; it skips the Projects and Archive folders. I assume that the problem has something to do with how I'm calling findstr but I haven't been able to identify the error of my ways. Any insight would be much appreciated!
Thanks so much!
-Alex
The FINDSTR /S option is causing it to search all folders, thus bypassing the intent of your FOR loop.
Stephan did successfully diagnose another problem with your code regarding redirection using overwrite instead of append mode.
But there is a much simpler method to get your desired result. Simply let FINDSTR search all folders, and pipe the result to an additional FINDSTR to remove results containing the unwanted folders. Since there is no loop, you can safely use owverwrite mode for redirection.
findstr /misl request "%basedir%\*" | findstr /liv "\\projects\\ \\archive\\" >"%basedir%\Projects\list.txt"
EDIT
The above simple solution will waste time searching folders that will later get excluded. This could waste valuable time if those folders are huge.
The following script will not bother scanning the "%basedir%\Projects" or "%basedir%\Archive" folders.
#echo off
setlocal EnableDelayedExpansion
set basedir=C:\folder
>"%basedir%\Projects\list.txt" (
findstr /mil request "%basedir%\*"
for /f "eol=: delims=" %%F in (
'dir /a:d-h /b %basedir% ^| findstr /vixl "projects archive"'
) do findstr /smil request "%basedir%\%%F\*"
)
If you want to skip all folders named "Projects" or "Archive", regardless where they appear in the tree, then:
#echo off
setlocal EnableDelayedExpansion
set basedir=C:\folder
>"%basedir%\Projects\list.txt" (
findstr /mil request "%basedir%\*"
for /f "eol=: delims=" %%F in (
'dir /s /a:d-h /b %basedir% ^| findstr /vir "[\\]projects[\\] [\\]archive[\\] [\\]projects$ [\\]archive$"'
) do findstr /mil request "%%F\*"
)
I had a similar problem: I needed to use findstr to search all .js files except those in the node_modules folder (i.e., I wanted to search my code, but not the code of any imported modules). This is the command I used:
dir /S /B *.js | findstr /v /i node_modules | findstr /i /F:/ todo
Breaking that down:
dir /S /B *.js will output the full path of all .js files in the current directory and all subdirectories
findstr /v /i node_modules filters that list of paths and removes any path that contains the string "node_modules". (The /v flag makes findstr output lines that do not match.)
findstr /i /F:/ todo - The "/F:/" tells findstr to accept a list of file paths to search from the console.
So, only files that make it through the "node_modules" filter get searched.
your problem is: with the redirection > you overwrite your list.txt every time; the last time you overwrite it with an empty string.
Use >> (append to file) instead. The rest of your code is working for me.
Your code have a couple points difficult to follow. You want to skip folders, but for /f %%g in ('dir /a:-h /b %basedir% command get all non-hidden names, including both files and folders. At end you use > to store the results, so just the output of last findstr ... %%g is stored in that file. You must use >> instead as Stephan indicate. However, I still don't understand how you get that result!
I suggest you to modify your code in order to made it simpler, so it may be easier to follow and detect possible errors. For example:
setlocal EnableDelayedExpansion
set basedir=C:\folder
set omitfolders=\Projects\Archive\
cd %basedir%
for /D %%g in (*) do (
if "!omitfolders:\%%g\=!" equ "%omitfolders%" (
findstr /i /m /s /c:"request" %basedir%\%%g\*.* >> %basedir%\Projects\list.txt
)
)
The if "!omitfolders:\%%g\=!" equ "%omitfolders%" command test if the folder name is not in omitfolders variable.
I'm try to find, in only one row, the number of files (*.rar) in a directory.
For doing this I'm using the commands:
for /f "delims=" %i in ('find /c ".rar" "D:\backup e ckpdb ept-icd\test\unload\lista_files_rar.txt"') do echo %i
but the value of %i I have at the end is : D:\BACKUP E CKPDB EPT-ICD\TEST\UNLOAD\LISTA_FILES_RAR.TXT: 8
I would like to obtain only the number 8 so instead to echo the value I would assign the value to a variable.
I use the command line : dir /b *.rar | find /c ".rar"
that it returns the value of rar files in the directory, but I can't assign the value to a variable, for example: dir /b *.rar | find /c ".rar" | set/a files =
I tried also to use the keyword tokens=2 but it doesn't work
p.s If it possible to do it only with the find command is also better
See here for example on counting files
Or you can simply do something like this (not tested)
for /F %%j in ('dir /B *.rar ^| find /C /V ""') do set count=%%j
This returns just the number; there might be a cleaner way to do it, but unfortuantly "find" can't take it's input from a pipe (i.e., I can't do dir | find):
#echo off
dir /b *.rar> out.tmp
for /f "usebackq tokens=3" %%i in (`find /c "rar" out.tmp`) do echo %%i
del out.tmp
Try "delims=: tokens=3"
You normally will have two colons in the result, one after the drive letter and one before the number you want, so your number should be token 3
Thank you, I think I will use
for /F %%j in ('dir /B *.rar ^| find /C /V ""') do set count=%%j
user135127
In this way I think also if somethink in the name of the dir the result should remain always the same.
which is the difference between :
dir /B *.rar ^| find /C /V "" and
dir /B *.rar ^| find /C ".rar" ?
for /f %a in ('dir "*.txt" ^| find "File(s)"') do set Count=%a
Gives
set Count=36
or you can use an arithmetic set and delayed environment variable expansion
set count=0
for %a in (*.txt) do #set /a Count=!Count!+ 1 > nul
echo %count%
gives
Count=36