How do I write a windows batch file that stores all of the folder names in a directory in individual variables? I do not know how many folders will be in the directory at any given time. I'm pretty sure that I need a for loop.
Here is what I've tried so far:
#ECHO OFF
set /a c=1
setlocal ENABLEDELAYEDEXPANSION
for /d %%f in (c:\users\*) do echo.file %%f
for /d %%A in (c:\users\*) do (set "var!c!=%%A")
ECHO.%var!c!%
perhaps What you can do is write the output of command
dir /AD
in some file called as folders.txt then can do operations on number of folders by storing them into any an array variable , something like this.
for %%G in (folders.txt) do (
set /a count+=1
call :exec1 %%~nG
echo %%~nG
)
goto :continue1
:exec1
echo %count%
set mapArray[%count%]=%1
goto :end
:continue1
:end
Related
I have many folders in a directory which I need to rename with a fixed base name and a progressive number starting from 1 to infinite.
Path of folders have space and base folder is D:\Programmi Installati.
Example of folders to rename:
log_1
log_2
log_04-01-2019 15-15-11,51
log_01-01-2019 8-22-14,19
log_27-12-2018 14-23-18,28
log_aaaa
log_bbbb
log_5
log_6
log_02-01-2019 6-21-17,34
log_03-01-2019 21-18-16,22
Example of wanted folder names:
log_1
log_2
log_3
log_4
log_5
log_6
log_7
log_8
log_9
log_10
log_11
log_12
The numbers of folder to rename can be large, but the structure is the same.
I tryed more batch file but all fail when there are some folders with the wanted name (example log_5 or log_1)
The order is not important it is important that all the folders starting with "log" are renamed with an incrental number.
Code already tryed without success
:: 1 code
#echo off
setlocal enabledelayedexpansion
set counter=
for /d %%a in ("D:\Programmi Installati\log_*") do (
set /a counter+=1
ren "%%~fa" "log_!counter!"
)
pause
:: 2 code
#echo off
setlocal EnableExtensions EnableDelayedExpansion
set "Counter=1"
for /F "delims=" %%I in ('dir "D:\Programmi Installati\log*" /AD /B /ON 2^>nul') do ren "D:\Programmi Installati\%%I" "log_!Counter!" & set /A Counter+=1
endlocal
pause
:: 3 code
#ECHO OFF
#setlocal enabledelayedexpansion
Rem | Folder Path & CD To Location
Set "Folder=D:\Programmi Installati\"
CD %Folder%
Rem | Get Raw File Name
Set "Number=1"
for /F "tokens=*" %%A in ('dir "log*" /S /b /AD') do (
Rem | Rename Folder || Raw Name - %%~n1
rename "%%~nA" "log_!Number!"
Rem | Add One To Number
set /a "number+=1"
)
Goto :EOF
PAUSE
The codes over works only if there is no desired directory name in the directory otherwise do not rename folders.
This batch works differently, it
skips folders with the proper naming scheme (so they keep the number)
increments a counter and fills in possible gaps
:: Q:\Test\2019\01\11\SO_54149437.cmd
#Echo off
Pushd "D:\Programmi Installati\" || (Echo couldn't change dir&pause&goto :eof)
set Cnt=0
for /f "delims=" %%A in (
'dir /B /AD log_* ^| findstr /iV "^log_[0-9][0-9]*$" '
) Do Call :RenInc "%%A"
PopD
Goto :Eof
:RenInc
Set /A Cnt+=1
if Exist "log_%Cnt%" goto :RenInc
Ren "%~1" "log_%Cnt%"
The resulting names (there are only eleven, not twelve)
log_1
log_10
log_11
log_2
log_3
log_4
log_5
log_6
log_7
log_8
log_9
So what I'm trying to do is, i have a bat file that makes timestamped backups(for example, 180126_053327 in the format: yymmdd_hhmmss). I'm trying to create this bat to add to it, so i can have it lookup those backups, display in console to allow the user to select the backup they want to restore by inputting the number they want and then copy it to a location.
so far what i have creates this:
Pic of what I have so far
The pic above is from the following script:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
set i=0
For /f %%a in ('dir I:\AM_Configs-backups\ /B /A /D') do (
set /a i+=1
echo !i! %%a
set dir!i!=%%a
)
echo.
set /p uin="Select a directory [1-!i!]: "
set udir=!dir%uin%!
echo Selected - %udir%
md c:\test2
copy %udir% c:\test2
#PAUSE
I keep getting this:
Select a directory [1-29]: 27
Selected - 180126_053327
The system cannot find the file specified.
Press any key to continue . . .
I got the script above from this link: Prompting user to select directory in batch file
It cannot be found because %udir% is not in the current directory. This means that your base directory, I:\AM_Configs-backups, needs to be pre-fixed to your Copy command.
Copy "I:\AM_Configs-backups\%udir%" "C:\test2"
Also here is an alternative to the linked example you provided in your question:
#Echo Off
SetLocal EnableDelayedExpansion
Set "baseDir=I:\AM_Configs-backups"
For /F "Delims==" %%A In ('"(Set dir[) 2>Nul"') Do Set "%%A="
Set "i=0"
For /D %%A In ("%baseDir%\*") Do (Set /A i+=1 & Set "dir[!i!]=%%~nxA")
If %i% Equ 1 (Set "dir[X]=%baseDir%\%dir[1]%") Else Call :Menu
Rem Your commands using the selected directory begin below
Echo you selected %dir[X]%
If Not Exist "C:\test2\" MD "C:\test2"
Copy "%dir[X]%" "C:\test2"
Pause
Exit /B
:Menu
For /L %%A In (1,1,%i%) Do (Echo %%A. !dir[%%A]!)
Set /P "dir[X]=Select a directory from the above list: "
If Not Defined dir[%dir[X]%] (ClS & GoTo Menu)
Set "dir[X]=%baseDir%\!dir[%dir[X]%]!"
You can adjust your base directory on line 3 and put your own commands from line 9 onwards, (up to the Exit /B).
You should consider using RoboCopy for copying directories!
Edit
For the XCopy version, you'd probably need to change to:
#Echo Off
SetLocal EnableDelayedExpansion
Set "baseDir=I:\AM_Configs-backups"
For /F "Delims==" %%A In ('"(Set dir[) 2>Nul"') Do Set "%%A="
Set "i=0"
For /D %%A In ("%baseDir%\*") Do (Set /A i+=1 & Set "dir[!i!]=%%~nxA")
If %i% Equ 1 (Set "dir[X]=%dir[1]%") Else Call :Menu
Rem Your commands using the selected directory begin below
Echo you selected %dir[X]%
XCopy "%baseDir%\%dir[X]%" "%AppData%\Awesomeminer\%dir[X]%" /S /I /F /Y 2>Nul
Echo Starting Awesome Miner...
Start "" "%ProgramFiles(x86)%\Awesome Miner\AwesomeMiner.exe"
Pause
Call "Switch-N-Bkup.bat"
Pause
Exit /B
:Menu
For /L %%A In (1,1,%i%) Do (Echo %%A. !dir[%%A]!)
Set /P "dir[X]=Select a directory from the above list: "
If Not Defined dir[%dir[X]%] (ClS & GoTo Menu)
Set "dir[X]=!dir[%dir[X]%]!"
For the RoboCopy version you'd change line 11 to:
RoboCopy "%baseDir%\%dir[X]%" "C:\test2\%dir[X]%" /S 2>Nul
...plus any additional switches you may need
I ended up using this cus i have another batch for switching and backing up:
to kinda give you an idea, i have a primary bat for switching and copying configs, which will start teh program automatically after their copied. in that bat i also have code for backing up current configs to a location using time/date and creates the folders in this format: yymmdd_hhmmss...i needed an easy restore function, which with the link and code you provided helped with the user able to select which folder to restore and copying it to the programs data folder to be used, then auto-starting the program using the copied config.
#Echo Off
SetLocal EnableDelayedExpansion
Set "baseDir=I:\AM_Configs-backups"
For /F "Delims==" %%A In ('"(Set dir[) 2>Nul"') Do Set "%%A="
Set "i=0"
For /D %%A In ("%baseDir%\*") Do (Set /A i+=1 & Set "dir[!i!]=%%~nxA")
If %i% Equ 1 (Set "dir[X]=%baseDir%\%dir[1]%") Else Call :Menu
Rem Your commands using the selected directory begin below
Echo you selected %dir[X]%
REM If Not Exist "C:\test2\" MD "C:\test2"
xcopy "%dir[X]%" "%USERPROFILE%\AppData\Roaming\Awesomeminer\" /S /F /R /Y
START C:\"Program Files (x86)"\"Awesome Miner"\AwesomeMiner.exe
ECHO Starting Awesome Miner...
#Pause
CALL Switch-N-Bkup.bat
exit /b
:Menu
For /L %%A In (1,1,%i%) Do (Echo %%A. !dir[%%A]!)
Set /P "dir[X]=Select a directory from the above list: "
If Not Defined dir[%dir[X]%] (ClS & GoTo Menu)
Set "dir[X]=%baseDir%\!dir[%dir[X]%]!"
So in Windows Explorer, I have these files sorted like this:
I have this script to remove the brackets and one zero, and in case the trailing number is greater than or equal to 10, to remove two zeroes:
cd C:\folder
setlocal enabledelayedexpansion
SET /A COUNT=0
for %%a in (*.jpg) do (
SET /A COUNT+=1
ECHO !COUNT!
set f=%%a
IF !COUNT! GTR 9 (
set f=!f:^00 (=!
) ELSE (
set f=!f:^0 (=!
)
set f=!f:^)=!
ren "%%a" "!f!"
)
pause
However, once I run the code, I get this result:
So the batch file isn't going through the files "intuitively" like Windows Explorer shows them. Is there any way to change this? Or is there a better way to rename these files altogether?
This uses a different approach:
#echo off
cd C:\folder
setlocal enabledelayedexpansion
SET /A COUNT=0, REMOVE=2
for /F "delims=(" %%a in ('dir /B *.jpg') do (
SET /A COUNT+=1
ECHO !COUNT!
set "f=%%a"
IF !COUNT! EQU 10 SET "REMOVE=3"
for /F %%r in ("!REMOVE!") do set "f=!f:~0,-%%r!"
ren "%%a" "!f!!COUNT!.jpg"
)
pause
Here is a method that does not depend on the sort order used by the file system, preserving the numbers as occurring in the original file names.
For each file name (for instance, test_this_01 SELR_Opening_00000 (1).jpg), the portion after the last under-score _ is retrieved (00000 (1)). Then the parentheses and the space are removed and then the length is trimmed to five characters (00001). This string replaces the original one in the file name finally (test_this_01 SELR_Opening_00001.jpg); the file name must not contain the replaced portion (00000 (1)) multiple times (hence file names like this should not occur: test_this_00000 (1) SELR_Opening_00000 (1).jpg):
#echo off
setlocal DisableDelayedExpansion
rem // Define constants here:
set "LOCATION=."
set "PATTERN=*_* (*).jpg"
set /A "DIGITS=5"
pushd "%LOCATION%" || exit /B 1
for /F "usebackq eol=| delims=" %%F in (`
dir /B /A:-D /O:D /T:C "%PATTERN%"
`) do (
set "FILE=%%F"
setlocal EnableDelayedExpansion
set "LAST="
for %%I in ("!FILE:_=","!") do (
set "LAST=%%~nI" & set "FEXT=%%~xI"
set "FNEW=!FILE:%%~I=!"
)
set "LAST=!LAST:(=!" & set "LAST=!LAST:)=!"
set "LAST=!LAST: =!" & set "LAST=!LAST:~-5!"
ECHO ren "!FILE!" "!FNEW!!LAST!!FEXT!"
endlocal
)
popd
endlocal
exit /B
Adapt the directory location and the file search pattern in the top section of the script as you like.
After having tested, remove the upper-case ECHO command in order to actually rename files.
I've been working on a batch script (.bat) to change file name to the same folder name 3 levels up but no luck. I can only get it to rename 1 level up. There are multiple files in multiple folders.
Any help would be greatly appreciated.
I don't completely understand the intent of your current code. But the following will rename a given file based on the folder 3 levels up. Note that you can only rename one file with a given extension per folder using this strategy.
#echo off
setlocal
set "file=H:\Techs\Exported Videos\Scenario\1-CAS IED\Media player format\A8 West\abc.avi"
for %%A in ("%file%") do for %%B in ("%%~A\..\..\..") do ren "%%~A" "%%~nxB%%~xA"
Note that I include the extension of the folder name because folder names can include dots.
EDIT
Based on OP's comments, I believe the following will properly rename all relevant .avi files. The code has been tested, and works in my hands. Simply set the root and files values as appropriate.
#echo off
setlocal
set "root=H:\Techs\Exported Videos\Scenario"
set "files=*.avi"
for %%A in ("%root%\.") do set "root=%%~fA"
for /f "delims=" %%A in ('dir /b /s /a-d "%root%\%files%"') do (
for %%B in ("%%~A\..\..\..") do (
if /i "%%~dpB" equ "%root%\" ren "%%~A" "%%~nxB%%~xA"
)
)
you might try this:
#echo off &setlocal
set /a PathLevel=3
for %%a in (
"H:\Techs\Exported Videos\Scenario\1-CAS IED\Media player format\A8 West\1-CAS IED.avi"
"H:\Techs\Exported Videos\Scenario\2-SAF\Media player format\A8 PTZ\2-SAF.avi"
) do (
call:doit "%%~a"
)
goto:eof
:doit
set "fname=%~1"
set /a cnt=0
for %%a in ("%fname:\=","%") do set /a cnt+=1
set /a cnt-=PathLevel
for %%a in ("%fname:\=","%") do (
set /a cnt-=1
setlocal enabledelayedexpansion
if !cnt! equ 0 (
endlocal
set "nname=%%~a"
) else endlocal
)
echo ren "%fname%" "%nname%%~x1"
goto:eof
output is:
ren "H:\Techs\Exported Videos\Scenario\1-CAS IED\Media player format\A8 West\1-CAS IED.avi" "1-CAS IED.avi"
ren "H:\Techs\Exported Videos\Scenario\2-SAF\Media player format\A8 PTZ\2-SAF.avi" "2-SAF.avi"
I am writing a batch file that finds and executes all update.bat file inside all the directories dropped onto it.
The problem here is that I expect the arguments (i.e directories' path) comes in ordered by name but it turns out they are sorted by the modified date.
Is this the default behavior of Windows (Windows 7)? Any suggestion to solve this?
Here is my batch script:
#echo off
Setlocal EnableDelayedExpansion
if [%1]==[] goto :no_update_dropped
set LOG_FILE=update_log.txt
echo You are about to run these updates:
for %%G IN (%*) do (
if exist %%~sG\NUL echo %%G
)
pause
for %%G IN (%*) do (
if exist %%G\NUL (
if exist %%G\update.bat (
call %%G\update.bat %LOG_FILE%
) else (
echo No update.bat found in %%G.
goto :no_batch_found
)
)
)
goto :success
:no_update_dropped
echo NO UPDATE FOLDER FOUND
echo Drag and drop one or more update folder to run.
goto :exit
:no_batch_found
echo UPDATE NOT COMPLETED!
goto exit
:success
echo all updated has been run successfully
goto :exit
:exit
pause
Best Regards.
You can sort your argument list right in your for loop like this:
setlocal enabledelayedexpansion
for /f "delims=" %%a in ('(for %%i in (%*^) do #echo %%~i^)^|sort') do (
set dirname=%%a
set dirname=!dirname:~0,-1!
echo use "!dirname!" without the trailing space
)
P.S. It seems like sort appends a space to the end of string,(WTF ????) so you'll have to get rid of it. I changed the code.
Finally with the help of dbenham's explanation this becomes:
for /f "delims=" %%a in ('cmd /c "for %%i in (%*) do #echo %%~i"^|sort') do (
echo use "%%a"
)
P.P.S This should work safer with commas in names (of course, they must be quoted)
for /f "delims=" %%a in ('cmd /c ^"for %%i in ^(%*^) do #echo %%~i^"^|sort') do (
echo use "%%a"
)
I would change the input set.
You can order by name by using /on and to get directories
/ad
so all directories by name =
dir /ad /on