I want to convert .flac files from X:\Music\flac\flacfolder\name.flac to X:\Music\mp3\flacfolder\name.mp3 using ffmpeg, but I couldn't find how to loop through while passing the directory to a different command and manipulating it.
Usually, to process files recursively, I would suggest to use the for /R loop. However, in this situation, since I guess you want to copy the directory hierarchy from the source to the target folder, I do not use it, because it resolves to absolute paths only. Instead I use xcopy /L, which does not copy anything (due to /L), but lists all applicable items as paths relative to the source folder; then I wrap around a for /F loop to read the list of relative paths and to resolve them related to the target folder; in the loop body finally, the ffmpeg needs to be placed (define the options to your needs and remove the preceding upper-case ECHO after having tested; the ffmpeg tool does not receive any relative paths but absolute ones only for both input and output files):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SOURCE=X:\Music\flac\flacfolder" & rem // (absolute source path)
set "_TARGET=X:\Music\mp3\flacfolder" & rem // (absolute target path)
set "_PATTERN=*.flac" & rem // (pure file pattern for input files)
set "_FILEEXT=.mp3" & rem // (pure file extension of output files)
pushd "%_TARGET%" || exit /B 1
for /F "delims=" %%F in ('
cd /D "%_SOURCE%" ^&^& ^(rem/ list but do not copy: ^
^& xcopy /L /S /Y /I ".\%_PATTERN%" "%_TARGET%" ^
^| find ".\" ^& rem/ remove summary line;
^)
') do (
2> nul mkdir "%%~dpF."
rem // Set up the correct `ffmpeg` command line here:
ECHO ffmpeg -i "%_SOURCE%\%%~F" "%%~dpnF%_FILEEXT%"
)
popd
endlocal
exit /B
If you want the destination files in a flat folder structure instead, a for /R loop workes fine:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_SOURCE=X:\Music\flac\flacfolder" & rem // (absolute source path)
set "_TARGET=X:\Music\mp3\flacfolder" & rem // (absolute target path)
set "_PATTERN=*.flac" & rem // (pure file pattern for input files)
set "_FILEEXT=.mp3" & rem // (pure file extension of output files)
for /R "%_SOURCE%" %%F in ("%_PATTERN%") do (
rem // Set up the correct `ffmpeg` command line here:
ECHO ffmpeg -i "%_SOURCE%\%%~F" "%_TARGET%\%%~nF%_FILEEXT%"
)
endlocal
exit /B
Try something like:
#echo off
setlocal
set FLAC_FOLDER=c:\temp\flacfolder
set MP3_ROOT_FOLDER=c:\temp\mp3folder
echo Processing folder [%FLAC_FOLDER%]...
for /f "tokens=*" %%F in ('dir "%FLAC_FOLDER%\*.flac" /a-d /b') do call :PROCESS_FLAC_FILE "%FLAC_FOLDER%" "%%F"
goto END
:PROCESS_FLAC_FILE
set PFF_FOLDER=%1
set PFF_FILE=%2
set PFF_FOLDER=%PFF_FOLDER:"=%
set PFF_FILE=%PFF_FILE:"=%
for /f %%I in ("%PFF_FILE%") do set PFF_MP3_FILE=%%~nI.mp3
echo Processing FLAC file [%PFF_FILE%] in folder [%PFF_FOLDER%]; output file is [%PFF_MP3_FILE%]...
REM Now call ffmpeg using the approriate variables. Enclose the variables in double-quotes, e.g.:
REM (note, I don't know the syntax for ffmpeg, so I'm making this up as an example)
ffmpeg.exe -source "%PFF_FOLDER%\%PFF_FILE%" -target "%MP3_ROOT_FOLDER%\%PFF_MP3_FILE%"
goto END
:END
I have an example I used in the past. I tried adding your structure to it.
#echo off
cd X:\Music\flac\flacfolder
for /F "tokens=1 delims=" %%i IN ('dir /s /b ^| findstr .flac') do (
call :process_code "%%i"
)
goto end
:process_code
echo Running conversion for %1
:: Run your process here
goto :eof
:end
echo done!
I hope this helps
Related
I'm trying to move several similar files into folders based on the filename.
The code below works fine but does not work if the base name is more than 5 characters, then it says the directory already exists, and moves the files to the shorter named folder.
The idea is to make folders based on a text file, and move it together with pictures which start with the same name (up to an "_" to that same folder, while the filenames remain intact. The picture names are longer though with varying lengths.
eg:
SB12.txt
SB123.txt
SB1234.txt
SB12345.txt
SB123_V_05062020.jpg
SB123_VT_05062020.jpg
SB12345_V_05062020.jpg
SB12345_VT_05062020.jpg
I tried adding delims=_ to the loop parameters but does not work like this :
for /f "tokens=* delims=_ " %%f in ('dir /b /on "%dir%\*%ext%"') do (
I already "solved" the longer name problem by changing the wildcard to >.* like the line below, but then the pictures don't get moved:
move "%dir%\!thefile!>.*" "%dir%\%yyyymmdd%\!thefile!\"
full code:
#echo off
setlocal
REM store current directory. Using separate variable makes it easier to change behavior too.
set dir=%cd%
REM make date fitting for folder needs
for /f "tokens=2-4 delims=/ " %%i in ('date /t') do set yyyymmdd=%%k\%%j\%%i
REM call subroutine for each supported extension.
call :dotxt .txt
REM call :dojpg .jpg
REM Main program done.
echo Press a key to close.
pause
exit /b
:dotxt
set ext=%1
REM loop through all files with the given extension.
for /f "tokens=*" %%f in ('dir /b /on "%dir%\*%ext%"') do (
REM trim the extension and use the base name as directory name.
setlocal EnableDelayedExpansion
set thefile=%%~nf
echo !thefile!
md "%dir%\%yyyymmdd%\!thefile!"
REM move all files that start with the same base name.
move "%dir%\!thefile!*.*" "%dir%\%yyyymmdd%\!thefile!\"
)
%SystemRoot%\explorer.exe %dir%\%yyyymmdd%
REM exit subroutine
exit /b
I think I might need an additional loop or another "set" option but can't get it figured out on my own.
A somewhat easier way, assuming you've already defined Dir and yyyymmdd
#Echo off
Set "Dir=Path of Root\"
Set "yyyymmdd=Define Date Substring"
::: { Set environment state for Macro Definitions
Setlocal DisableDelayedExpansion
(Set LF=^
%= Above Empty lines Required =%)
Set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"
::: { Macro for relocation of files to folders using Substring of Filename
::: - Usage:
::: %MOVEIF%{Search String*.Extension}{Destination Directory}
%= Capture Arguments =%
SET MOVEIF=For %%n in (1 2) Do If %%n==2 (%\n%
%= Split arguments using braces as delims =%
For /F "Tokens=1,2 Delims={}" %%G in ("!ITEM!") Do (%\n%
%= Use Arg 1 as search pattern for files in current and sub directories =%
For /F "Delims=" %%F in ('dir "%%~G" /b /s') do (%\n%
%= Split the name of file from _ for use as folder name =%
For /F "Tokens=1 Delims=_" %%N in ("%%~nF") Do (%\n%
%= Test / Create Subfolder in target Subdirectory using Arg 2 =%
IF Not exist "%%~H\%%~N" MD "%%~H\%%~N"%\n%
%= Execute move =%
Move "%%~F" "%%~H\%%~N"%\n%
)%\n%
)%\n%
)%\n%
) Else Set ITEM=
::: }
::: - enable macro, execute with args.
Setlocal EnableDelayedExpansion
CD "%Dir%" && For %%x in (jpg txt) Do For %%p in (SB) Do (%MOVEIF%{%%~p*.%%~x}{%Dir%%yyyymmdd%}) 2> Nul
Pause
Exit /B 0
Note: It isn't necessary to use a macro to achieve this, however it makes it very easy to use the code for other search strings or directories, as there is no need to edit the macro, you just call it with different parameters.
This is not a particularly complex task – here is a possible script (see all the rem comments):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=%~dp0." & rem // (path to directory containing target files)
set "_MASK=SB*.txt" & rem /* (file name pattern to find the master files,
rem which sub-directory names are derived from) */
set "_SUFF=_*.jpg" & rem /* (suffix pattern to be appended to the base
rem name of a master file to find related slave
rem files, which are to be moved in addition) */
rem // Change into the root directory:
pushd "%_ROOT%" && (
rem // Loop through the found master files:
for /F "delims= eol=|" %%F in ('dir /B /A:-D-H-S "%_MASK%"') do (
rem // Create sub-directory with base name of current master file:
md "%%~nF" 2> nul
rem // Move the master file into the sub-directory:
move "%%F" "%%~nF\" > nul
rem // Move related slave files into the sub-directory:
if exist "%%~nF%_SUFF%" move "%%~nF%_SUFF%" "%%~nF\" > nul
)
rem // Return from the root directory:
popd
)
endlocal
exit /B
With some help I was able to get my script working, it just doesnt like spaces bu that's fine for me:
#echo off
setlocal
REM store current directory. Using separate variable makes it
REM easier to change behaviour too.
set dir=%cd%
REM make date fitting for folder needs
for /f "tokens=2-4 delims=/ " %%i in ('date /t') do set yyyymmdd=%%k\%%j\%%i
REM call subroutine for each supported extension.
call :do .txt
call :do .jpg
REM Main program done.
echo Press a key to close.
pause
exit /b
:do
set ext=%1
REM loop through all files with the given extension.
for /f %%f in ('dir /b /on "%dir%\*%ext%"') do (
echo %%f
for /f "tokens=1 delims=_." %%m in ("%%f") do (
echo %%m
REM Make the folder
if not exist "%dir%\%yyyymmdd%\%%m" mkdir "%dir%\%yyyymmdd%\%%m"
echo %dir%\%%m\%%f
move ".\%%f" "%dir%\%yyyymmdd%\%%m"
)
)
REM %SystemRoot%\explorer.exe %dir%\%yyyymmdd%
REM exit subroutine
exit /b
Thanks for the efforts
I would like to append recursively folder (and parent folder) names to each *.txt files that folder contains. After that I want to move all files to base folder and delete all folders. I need to achieve this in Windows BATCH script. For examle:
\BaseFolder\A01\B01\EX1.TXT
\BaseFolder\C01\EX2.TXT
\BaseFolder\EX3.TXT
To:
\BaseFolder\A01-B01-EX1.TXT
\BaseFolder\C01-EX2.TXT
\BaseFolder\EX3.TXT
To do this i've found this solution thanks to JosefZ:
Recursively append folder name to the files in Windows batch file
#echo OFF
SETLOCAL EnableExtensions
for /F "delims=" %%G in ('dir /B /S "C:\Source\*.txt"') do (
for %%g in ("%%~dpG.") do rename "%%~fG" "%%~nxg_%%~nxG"
)
pause
where the FOR loops are:
outer %%G loop creates a static list of .txt files (recursively), and
inner %%g loop gets the parent folder of every particular file.
But this solve only a part of my goal. Can anyone help?
Here's a 'fun' idea:
#Set "BaseFolder=C:\Users\Mustafa\BaseFolder"
#ForFiles /P "%BaseFolder%" /S /M *.txt /C "Cmd /C If #IsDir==FALSE For /F 0x22Tokens=*Delims=.\0x22 %%# In (#RelPath)Do #If Not 0x22%%#0x22==#File Set 0x22_=%%#0x22&Call Move /Y 0x22%BaseFolder%\%%#0x22 0x22%BaseFolder%\%%_:\=-%%0x22>NUL"
Please note that this untested solution is very likely to have command line length limitations. I would therefore avoid it if your initial base folder is deep within the volume and/or its tree is deep or carries long file and directory names. Given that cautionary information, please remember to adjust the full path value on line one as necessary.
The following script should accomplish what you want, namely moving and renaming the files as predefined and deleting the remaining empty sub-directories (see all the explanatory rem remarks):
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "_ROOT=.\BaseFolder" & rem // (target base directory)
set "_MASK=*.txt" & rem // (file search pattern)
set "_CHAR=-" & rem // (separator character)
rem // Switch to target directory:
pushd "%_ROOT%" && (
rem // Loop through list of relative paths of matching files:
for /F "tokens=1* delims=:" %%E in ('
xcopy /L /S /I "%_MASK%" "%TEMP%" ^| find ":"
') do (
rem // Store current relative file path, initialise variables:
set "FILE=%%F" & set "NAME=" & set /A "NUM=0"
rem // Toggle delayed expansion to avoid trouble with `!` and `^`:
setlocal EnableDelayedExpansion
rem // Loop through all individual elements of file relative path:
for %%I in ("!FILE:\=" "!") do (
endlocal
rem // Store current path element and count them:
set "ITEM=%%~I" & set /A "NUM+=1"
setlocal EnableDelayedExpansion
rem // Build new file name and pass it over `endlocal` barrier:
for /F "delims=" %%N in ("!NAME!%_CHAR%!ITEM!") do (
endlocal
set "NAME=%%N"
setlocal EnableDelayedExpansion
)
)
rem // Finalise new file name:
if defined _CHAR set "NAME=!NAME:*%_CHAR%=!"
rem // Actually move and rename the current file:
> nul move "!FILE!" "!NAME!"
rem // Switch to parent directory of current file:
pushd "!FILE!\.." && (
rem // Loop through parent directory elements:
for /L %%N in (2,1,!NUM!) do (
rem // Try to remove parent directory when empty, go one up:
set "DD=!CD!" & cd ".." & 2> nul rd "!DD!"
)
rem // Return to previous working directory:
popd
)
endlocal
)
rem // return to original working directory:
popd
)
endlocal
exit /B
I have files named as RabcdYYMMKKACCOUNT.TXT in the Subfolders of a folder where YYMM is year, month this will change. KK is another identifier, I want all the files to be renamed to MSFKKDNB.ABC, the KK is the identifier in the input file.
Below is the one i tried and the result of it:
FOR /R %%f IN (*account.txt) DO REN "%%f" *dnb.abc
R00531706AUAccount.txt is renamed to R00531706AUAccount.txtdnb.abc
but the output should be MSFAUDNB.abc
This could be done for example with:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for /R %%I in (???????????account.txt) do (
set "FileName=%%~nI"
set "NewFileName=MSF!FileName:~9,2!DNB.abc"
if not exist "%%~dpI!NewFileName!" (
ren "%%~fI" "!NewFileName!" 2>nul
if not exist "%%~dpI!NewFileName!" echo Failed to rename file: "%%~fI"
) else (
echo Cannot rename file: "%%~fI"
)
)
endlocal
The file name of found account text file is assigned to environment variable FileName.
The new name for the file is created by concatenating the fixed parts MSF and DNB.abc with the 2 characters to keep from file name using string substitution and delayed expansion.
Next it is checked if a file with new name does not already exist. Is this the case the file renaming is done otherwise an error message is output.
After renaming the file it is checked if that was successful. A slightly different error is output if renaming failed for example because of a sharing violation.
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.
echo /?
endlocal /?
for /?
if /?
ren /?
set /?
setlocal /?
Read also the Microsoft article about Using Command Redirection Operators.
Try this:
#Echo Off
For %%A In ("*account.txt") Do (Set "_=%%~nA"
SetLocal EnableDelayedExpansion
Ren "%%A" "MSF!_:~-9,2!DNB.abc"
EndLocal)
I would probably do it the following way, provided that the files to rename are located in immediate sub-directories (YYMM) of the given root directory and nowhere else:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_ROOT=." & rem // (specify path to the root directory)
for /D %%D in ("%_ROOT%\????") do (
for %%F in ("%_ROOT%\%%~nxD\R??????????Account.txt") do (
set "FDIR=%%~nxD" & set "FILE=%%~nxF"
setlocal EnableDelayedExpansion
ECHO ren "!_ROOT!\!FDIR!\!FILE!" "MSF!FILE:~9,2!DNB.abc"
endlocal
)
)
endlocal
exit /B
If you want to check whether both the sub-directory name and the year/month portion of the file names are purely numeric, you could use the following script:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "_ROOT=." & rem // (specify path to the root directory)
for /F "delims= eol=|" %%D in ('
dir /B /A:D "%_ROOT%\????" ^| ^
findstr "^[0123456789][0123456789][0123456789][0123456789]$"
') do (
for /F "delims= eol=|" %%F in ('
dir /B /A:-D "%_ROOT%\%%~nxD\R??????????Account.txt" ^| ^
findstr "^R....[0123456789][0123456789][0123456789][0123456789].."
') do (
set "FDIR=%%~nxD" & set "FILE=%%~nxF"
setlocal EnableDelayedExpansion
ECHO ren "!_ROOT!\!FDIR!\!FILE!" "MSF!FILE:~9,2!DNB.abc"
endlocal
)
)
endlocal
exit /B
If you want to check whether the sub-directory name matches the year/month (YYMM) portion of the file names, replace the pattern R??????????Account.txt by R????%%~nxD??Account.txt (for both scripts).
After having verified the correct output of either script, remove the upper-case ECHO commands to actually rename any files!
Basically, both scripts use sub-string expansion to extract the identifier part (KK) from the file names. Since there are variables set and read in the same block of code, delayed expansion is required for that. The second approach does not list the sub-directories and files by standard for loops, it uses the dir command, findstr to filter their names and a for /F loop to capture the resulting output for both sub-directories and files.
How to write a Batch program that can move files with .txt from a folder (including files in sub-folder) in to a different folder and rename it in the form folderName_subfolderName_Filename.extension
This following snippet should do the trick. Modify it to your needs.
#ECHO OFF
REM Put the source and destination folde names here.
REM You can use %1 and %2 instead if you want to pass
REM folders as command line parameters
SET SOURCE_FOLDER=C:\SRC
SET TARGET_FOLDER=C:\DST
REM This is needed for variable modification inside the FOR loop
SETLOCAL ENABLEDELAYEDEXPANSION
REM The FOR loop lists all files recursively beginning in
REM %SOURCE_FOLDER% matching the *.txt pattern.
REM Filenames can be accessed in th loop via the %%F variable
FOR /R %SOURCE_FOLDER% %%F IN (*.txt) DO (
REM Put the path and filename into the FILE_NAME variable
SET FILE_NAME=%%~pnxF
REM Transform the path to new filename
REM (replace '\' with '_' and strip the first '\')
SET FILE_NAME=!FILE_NAME:\=_!
SET FILE_NAME=!FILE_NAME:~1!
REM This is the actual MOVE command creating the
REM targest filename from the variables.
MOVE "%%F" "%TARGET_FOLDER%\!FILE_NAME!"
)
adopted solution:
usage: moveit TargetFolder DestinationFolder NameOfTargetFolder
Sample: moveit C:\MyFolder C:\MySecondFolder MyFolder
moveit.bat:
Set target=%~1
Set destination=%~2
Set prefix=%~3
for /f "tokens=*" %%f in ('dir /b %target%\*.txt') do move "%target%\%%f" "%destination%\%prefix%_%%f"
for /f "tokens=*" %%s in ('dir /b/ad %target%\*') do call moveit.bat "%target%\%%s" "%destination%" %prefix%_%%s
How can I iterate over each file in a directory using a for loop?
And how could I tell if a certain entry is a directory or if it's just a file?
This lists all the files (and only the files) in the current directory and its subdirectories recursively:
for /r %i in (*) do echo %i
Also if you run that command in a batch file you need to double the % signs.
for /r %%i in (*) do echo %%i
(thanks #agnul)
Iterate through...
...files in current dir: for %f in (.\*) do #echo %f
...subdirs in current dir: for /D %s in (.\*) do #echo %s
...files in current and all subdirs: for /R %f in (.\*) do #echo %f
...subdirs in current and all subdirs: for /R /D %s in (.\*) do #echo %s
Unfortunately I did not find any way to iterate over files and subdirs at the same time.
Just use cygwin with its bash for much more functionality.
Apart from this: Did you notice, that the buildin help of MS Windows is a great resource for descriptions of cmd's command line syntax?
Also have a look here: http://technet.microsoft.com/en-us/library/bb490890.aspx
To iterate over each file a for loop will work:
for %%f in (directory\path\*) do ( something_here )
In my case I also wanted the file content, name, etc.
This lead to a few issues and I thought my use case might help. Here is a loop that reads info from each '.txt' file in a directory and allows you do do something with it (setx for instance).
#ECHO OFF
setlocal enabledelayedexpansion
for %%f in (directory\path\*.txt) do (
set /p val=<%%f
echo "fullname: %%f"
echo "name: %%~nf"
echo "contents: !val!"
)
*Limitation: val<=%%f will only get the first line of the file.
There is a subtle difference between running FOR from the command line and from a batch file. In a batch file, you need to put two % characters in front of each variable reference.
From a command line:
FOR %i IN (*) DO ECHO %i
From a batch file:
FOR %%i IN (*) DO ECHO %%i
This for-loop will list all files in a directory.
pushd somedir
for /f "delims=" %%f in ('dir /b /a-d-h-s') do echo %%f
popd
"delims=" is useful to show long filenames with spaces in it....
'/b" show only names, not size dates etc..
Some things to know about dir's /a argument.
Any use of "/a" would list everything, including hidden and system attributes.
"/ad" would only show subdirectories, including hidden and system ones.
"/a-d" argument eliminates content with 'D'irectory attribute.
"/a-d-h-s" will show everything, but entries with 'D'irectory, 'H'idden 'S'ystem attribute.
If you use this on the commandline, remove a "%".
Hope this helps.
%1 refers to the first argument passed in and can't be used in an iterator.
Try this:
#echo off
for %%i in (*.*) do echo %%i
I had trouble getting jop's answer to work with an absolute path until I found this reference: https://ss64.com/nt/for_r.html
The following example loops through all files in a directory given by the absolute path.
For /R C:\absoulte\path\ %%G IN (*.*) do (
Echo %%G
)
Here's my go with comments in the code.
I'm just brushing up by biatch skills so forgive any blatant errors.
I tried to write an all in one solution as best I can with a little modification where the user requires it.
Some important notes: Just change the variable recursive to FALSE if you only want the root directories files and folders processed. Otherwise, it goes through all folders and files.
C&C most welcome...
#echo off
title %~nx0
chcp 65001 >NUL
set "dir=c:\users\%username%\desktop"
::
:: Recursive Loop routine - First Written by Ste on - 2020.01.24 - Rev 1
::
setlocal EnableDelayedExpansion
rem THIS IS A RECURSIVE SOLUTION [ALBEIT IF YOU CHANGE THE RECURSIVE TO FALSE, NO]
rem By removing the /s switch from the first loop if you want to loop through
rem the base folder only.
set recursive=TRUE
if %recursive% equ TRUE ( set recursive=/s ) else ( set recursive= )
endlocal & set recursive=%recursive%
cd /d %dir%
echo Directory %cd%
for %%F in ("*") do (echo → %%F) %= Loop through the current directory. =%
for /f "delims==" %%D in ('dir "%dir%" /ad /b %recursive%') do ( %= Loop through the sub-directories only if the recursive variable is TRUE. =%
echo Directory %%D
echo %recursive% | find "/s" >NUL 2>NUL && (
pushd %%D
cd /d %%D
for /f "delims==" %%F in ('dir "*" /b') do ( %= Then loop through each pushd' folder and work on the files and folders =%
echo %%~aF | find /v "d" >NUL 2>NUL && ( %= This will weed out the directories by checking their attributes for the lack of 'd' with the /v switch therefore you can now work on the files only. =%
rem You can do stuff to your files here.
rem Below are some examples of the info you can get by expanding the %%F variable.
rem Uncomment one at a time to see the results.
echo → %%~F &rem expands %%F removing any surrounding quotes (")
rem echo → %%~dF &rem expands %%F to a drive letter only
rem echo → %%~fF &rem expands %%F to a fully qualified path name
rem echo → %%~pF &rem expands %%A to a path only
rem echo → %%~nF &rem expands %%F to a file name only
rem echo → %%~xF &rem expands %%F to a file extension only
rem echo → %%~sF &rem expanded path contains short names only
rem echo → %%~aF &rem expands %%F to file attributes of file
rem echo → %%~tF &rem expands %%F to date/time of file
rem echo → %%~zF &rem expands %%F to size of file
rem echo → %%~dpF &rem expands %%F to a drive letter and path only
rem echo → %%~nxF &rem expands %%F to a file name and extension only
rem echo → %%~fsF &rem expands %%F to a full path name with short names only
rem echo → %%~dp$dir:F &rem searches the directories listed in the 'dir' environment variable and expands %%F to the fully qualified name of the first one found. If the environment variable name is not defined or the file is not found by the search, then this modifier expands to the empty string
rem echo → %%~ftzaF &rem expands %%F to a DIR like output line
)
)
popd
)
)
echo/ & pause & cls
To iterate through all files and folders you can use
for /F "delims=" %%a in ('dir /b /s') do echo %%a
To iterate through all folders only not with files, then you can use
for /F "delims=" %%a in ('dir /a:d /b /s') do echo %%a
Where /s will give all results throughout the directory tree in unlimited depth. You can skip /s if you want to iterate through the content of that folder not their sub folder
Implementing search in iteration
To iterate through a particular named files and folders you can search for the name and iterate using for loop
for /F "delims=" %%a in ('dir "file or folder name" /b /s') do echo %%a
To iterate through a particular named folders/directories and not files, then use /AD in the same command
for /F "delims=" %%a in ('dir "folder name" /b /AD /s') do echo %%a
for %1 in (*.*) do echo %1
Try "HELP FOR" in cmd for a full guide
This is the guide for XP commands. http://www.ss64.com/nt/
The following code creates a file Named "AllFilesInCurrentDirectorylist.txt" in the current Directory, which contains the list of all files (Only Files) in the current Directory. Check it out
dir /b /a-d > AllFilesInCurrentDirectorylist.txt
It could also use the forfiles command:
forfiles /s
and also check if it is a directory
forfiles /p c:\ /s /m *.* /c "cmd /c if #isdir==true echo #file is a directory"
I would use vbscript (Windows Scripting Host), because in batch I'm sure you cannot tell that a name is a file or a directory.
In vbs, it can be something like this:
Dim fileSystemObject
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
Dim mainFolder
Set mainFolder = fileSystemObject.GetFolder(myFolder)
Dim files
Set files = mainFolder.Files
For Each file in files
...
Next
Dim subFolders
Set subFolders = mainFolder.SubFolders
For Each folder in subFolders
...
Next
Check FileSystemObject on MSDN.
I use the xcopy command with the /L option to get the file names. So if you want to get either a directory or all the files in the subdirectory you could do something like this:
for /f "delims=" %%a IN ('xcopy "D:\*.pdf" c:\ /l') do echo %%a
I just use the c:\ as the destination because it always exists on windows systems and it is not copying so it does not matter. if you want the subdirectories too just use /s option on the end. You can also use the other switches of xcopy if you need them for other reasons.
Try this to test if a file is a directory:
FOR /F "delims=" %I IN ('DIR /B /AD "filename" 2^>^&1 ^>NUL') DO IF "%I" == "File Not Found" ECHO Not a directory
This only will tell you whether a file is NOT a directory, which will also be true if the file doesn't exist, so be sure to check for that first if you need to. The carets (^) are used to escape the redirect symbols and the file listing output is redirected to NUL to prevent it from being displayed, while the DIR listing's error output is redirected to the output so you can test against DIR's message "File Not Found".
try this:
::Example directory
set SetupDir=C:\Users
::Loop in the folder with "/r" to search in recursive folders, %%f being a loop ::variable
for /r "%SetupDir%" %%f in (*.msi *.exe) do set /a counter+=1
echo there are %counter% files in your folder
it counts .msi and .exe files in your directory (and in the sub directory). So it also makes the difference between folders and files as executables.
Just add an extension (.pptx .docx ..) if you need to filter other files in the loop
In my case I had to delete all the files and folders underneath a temp folder. So this is how I ended up doing it. I had to run two loops one for file and one for folders. If files or folders have spaces in their names then you have to use " "
cd %USERPROFILE%\AppData\Local\Temp\
rem files only
for /r %%a in (*) do (
echo deleting file "%%a" ...
if exist "%%a" del /s /q "%%a"
)
rem folders only
for /D %%a in (*) do (
echo deleting folder "%%a" ...
if exist "%%a" rmdir /s /q "%%a"
)