I'm starting to learn how to use the CMD in Windows. And I have a directory full of documents with names like "Document_1.txt", "Document_5.txt" etc... (All with Document_#.txt but there's no pattern in the numbers).
I want to move each file to a folder named "Text_#" and change the name of the file to "text_#.txt". How can I do that?
My attempt is this (simple) batch file (actually I think I don't even need to create a batch file, but was easy to do this way.)
#ECHO OFF
FOR /L %%i IN (1,1,24) DO (
FORFILES /M *.txt /C "cmd /c IF #fname==Document_%%i (MD Text_%%i) & (MOVE #file Text_%%i\text_%%i.txt)"
The problem is that the IF command never returns true, although when writing ECHO #fname it prints "Document_#", so I suppose that even if what I see is the same there is some difference that I cant see using the ECHO command.
Anybody could give me some solution to this problem?
In my opinion the simplest way is to forget about using the ForFiles command for this, and use a For /F loop instead. To ensure that only the files with a .txt extension whose basename ends with _# or _##, (where # represents an integer), use the Dir command and filter its results with the help of FindStr. Then you can use MD to make the directories if it don't already exist and move the files into it, renaming them with their new name.
From the cmd with the current directory as that holding your files:
For /F "Tokens=1,* Delims=_" %G In ('Dir /B /A -D Document_??.txt ^| %__AppDir__%findStr.exe /I "_[0123456789]*\.txt$"') Do #If Not Exist Text_%~nH (MD Text_%~nH) & Move /Y %G_%H Text_%~nH\text_%H 1>NUL
If you want to do that from a batch-file instead, also within the same current directory:
#For /F "Tokens=1,* Delims=_" %%G In (
'Dir /B /A -D Document_??.txt ^| %__AppDir__%findStr.exe /I "_[0123456789]*\.txt$"'
) Do #(
If Not Exist Text_%%~nH MD Text_%%~nH
Move /Y %%G_%%H Text_%%~nH\text_%%H 1>NUL
)
The above answers assume either one or two digits at the end of the file basenames, (as you were limiting yours to numbers from 1 to 24 inclusive) I have also left out quoting because your provided names didn't warrant it. If those were not truly representative, you'll need to introduce those as necessary and make any other changes which were outside of the question posed.
Related
I am trying to use a batch script to delete files that has a ( in its name. For example, the file that I would like to delete has the name "Test1 - Copy (5).txt".
I tried this command but it does not work:
for /f "delims=" %%a in ('
findstr /l /i /m /c:"(" "C:\Users\Desktop\New folder\*.*"
') do echo del "%%a"
Can you assist me in getting the correct code to delete the files that has a ( in its name? Thanks!
Usually when someone online gives you code that could be destructive (like code to delete a bunch of files), they'll preface the delete command with an echo so that you can see what commands would be run. In order to actually run the command, simply remove the echo:
for /f "delims=" %%a in ('findstr /l /i /m /c:"(" "C:\Users\Desktop\New folder\*.*"') do del "%%~a"
However, this is a lot of typing (and it's doing a case-insensitive search for an open parentheses for some reason), so you can simply use wildcards to delete any files whose name contain the string you're looking for:
del "%USERPROFILE%\Desktop\New folder\*(*"
I would like to recursively delete all files with a specific extension in a batch file.
I am aware of the following command:
del /s *.ext
However, this does on Windows also delete files with other extensions like e.g. .ext1 or .ext2 . The reason for this seems to be that the 8.3 file name of such a file ends with .ext and therefore also the files with longer extensions are matched.
I am looking for a replacement to the command above that recursively deletes all files with .ext extension but keeps files with longer extensions.
the where command works a bit differently (in regards to wildcards and short-names). Put a for /f loop around, and you're done. Your example would then translate to:
for /f "delims=" %%a in ('where /r . *.ext') do ECHO del "%%a"
Note: I disarmed the del command by just echoing it. Remove the ECHO after troubleshooting, when you are sure it does exactly what you want.
This also uses where.exe, but takes account of an issue not mentioned in another answer.
The issue is that where searches append each extension listed under %PATHEXT% to your .ext glob/spec. So whilst it will delete your target files, excluding files like .ext1 and .ext2 etc. it will now include for example, *.ext.com, *.ext.exe, *.ext.bat, *.ext.cmd, *.ext.vbs, *.ext.vbe, *.ext.js, *.ext.jse, *.ext.wsf, *.ext.wsh, and *.ext.msc etc.
The fix is to simply empty the content of %PATHEXT% before issuing the command. The following method does so within the For loop parenthsized command. As that is ran in another cmd.exe instance, it will not affect the instance in which the rest of your script resides:
#For /F "Delims=" %%G In ('"(Set PATHEXT=) & "%__APPDIR__%where.exe" /F /R "C:\SourceDir" "*.ext" 2>NUL"') Do #Del /A /F %%G
Obviously, you would modify, C:\SourceDir to contain the root location you require. The other current answers, use the current directory. If you want that, change it to ., or if you want the directory base as that of your batch file, change it to %~dp0.. Please do not remove any doublequotes.
Here are some alternative method examples, (please remember to adjust the drive/path/extension as needed)
If you wish to stick with the more traditional Dir command, then you could pipe the results through the findstr.exe utility, to exclude those matching the 8.3 names:
#For /F "Delims=" %%G In ('"Dir /B /S /A:-D "C:\SourceDir\*.ext" 2> NUL | "%__APPDIR__%findstr.exe" /I /L /E ".ext""') Do #Del /A /F "%%G"
You could also use the forfiles.exe utility for the task:
#"%__APPDIR__%forfiles.exe" /P "C:\SourceDir" /S /M "*.ext" /C "\"%__APPDIR__%cmd.exe\" /C \"If #IsDir==FALSE Del /A /F #File\""
Or this excruciatingly slow WMIC.exe utility method:
#"%__APPDIR__%wbem\WMIC.exe" DataFile Where "Drive='C:' And Path Like '\\SourceDir\\%%' And Extension='ext'" Delete 1> NUL 2>&1
Stephans answer is the shorter version, but you can use findstr's regex as well to match that the end of the name should be .ext
for /f "delims=" %%i in ('dir /b /s ^| findstr /IRC:"\.ext$"') do echo del "%%~i"
I need to count the number of .txt files in a Windows 10 directory.
I am starting with the following code as a batch-file:
#ECHO OFF
for %%f in (*.*) do echo %%f
Does anyone know how I can do it?
The method will most likely depend upon the rest of the script; but for the question only.
Probably the simplest method would be to use where.exe and find.exe together:
Where .:*.txt 2>Nul|Find /C /V ""
Should you wish to save the count as the value content of a variable, you can use a For /F loop incorporating either where.exe or the Dir command. Please note however that in both a standard For loop, (For %%A In (*.txt)), and when using the Dir command, (Dir *.txt), file extensions beginning with .txt are returned as opposed to those ending with .txt, returned by where.exe. In order to account for this, in my Dir version, I have piped the results through a findstr.exe to ensure that only .txt files are counted:
Where method:
#Echo Off
Set "#=0"
For /F %%A In ('"Where .:*.txt 2>Nul|Find /C /V """')Do Set "#=%%A"
Echo(%#%
Pause
Dir method:
#Echo Off
Set "#=0"
For /F %%A In ('"Dir/B/A-D-L *.txt 2>Nul|FindStr/I "txt$"|Find /C /V """'
)Do Set "#=%%A"
Echo(%#%
Pause
In advance: I'm new to batch or programming in general so please explain as much as possible.
My problem:
I want to delete all folders not named X and Y in a directory Z (ex. D:\Test\z)
So let's say Z contains these folder:
backup
resources
project1
project2
project3
I'd need to exclude only backup and resources from deletion via a script.
I looked up multiple soultions for not deleting only one folder with a certain name but I don't know if it's possible for multiple values with Batch.
not tested:
#echo off
set "root_dir=C:\Z"
set "exclude_list=backup resources"
pushd "%root_dir%"
for /f "tokens=* delims=" %%# in ('dir /b /a:d^| findstr /v "%exclude_list%"') do (
echo rd /s /q "%%~f#"
)
if this looks ok delete the echo on the last line to activate deletion.
If all folders you want to delete are like project* you can try also :
for /d %%a in ("project*") do rd /s /q "%%~fa"
#echo off
setlocal EnableDelayedExpansion
rem Define working variables
set "dir=D:\Test\z"
set "exclude=/backup/resources/"
rem Change current dir to working dir
cd /D "%dir%"
rem Process all folders in this dir
for /D %%f in (*) do (
rem If current folder is not in "exclude" var
if "!exclude:/%%f/=!" equ "%exclude%" (
rem Delete it
ECHO rd /s /q "%%f"
)
)
This method use internal cmd.exe commands only, so it run faster than other methods that may use external .exe files (like findstr.exe).
The way to detect if a name is in the exclude variable is trying to delete such name from it: "%exclude:/%%f/=%": if the result is equal to the original variable contents, the folder was not there. This method is very simple and efficient and works not matter the case of the letters, so it don't requires any /I ignore case switch in the if command.
The names are delimited by slashes to avoid any problem caused by partial name matches; for this reason the %%f part is enclosed in slashes in the if command.
Note that the value of %%f change in each iteration of the for command. For this reason, the exclude variable is surrounded by exclamation marks instead percent signs and the setlocal EnableDelayedExpansion command is given at beginning; otherwise, the %expansion% would be done just one time, before the for command start iterations. You may look for "delayed expansion" in this forum for a further explanation of this point.
I need help with a script that first finds all files in a directory with a certain string, then uses the filenames in a variable to be used in a script.
So:
Find files and filenames
Saves file?
Start some kind of loop? that changes a variable then executes the
belonging script
Repeat till all filenames have been used.
My code here..
#Echo off
For /r C:\work %%G In (*) Do #Findstr /M /S "string" > filenames.txt %%G
Set Var1=0
For %%G In (*) Do (
Var1=<filenames.txt (???)
script
script
I haven't writen "script" myself and friend help me with it, if you would like to see it do you need to wait until I can get to my other computer at home.
Thanks on beforehand!
Find files and filenames
Saves file
set "search=what I want to find"
(for /f "delims=" %%a in ('dir /a-d /b /s "C:\work" ^| findstr "%search%"') do echo (%%~fa)>filenames.txt
Start some kind of loop? that changes a variable then executes the belonging script
Repeat till all filenames have been used.
for /f "delims=" %%a in (filenames.txt) do (
REM here do something inside the loop
REM until all file names from filenames.txt were processed
)
This is designed to find files in c:\work that match a string, and echo the filenames.
#echo off
cd /d "c:\work"
for %%a in ("*string*") do (
echo "%%a"
)