简体   繁体   中英

Batch How to avoid a same 2nd FOR loop?

I have created a batch script to backup some subfolders from a path A to a path B ( Z:\Folder1\… > U:\Backup\… ).

The script lists the subfolders inside path A and increments a number for each of them. Then, I just have to enter the number(s) of the subfolder(s) I want to backup and xcopy does the rest.

The problem is that sometimes I have thousands of subfolders in path A and only a few to backup (10 or 15).

What I would like is that once I enter the number of these folders, it will go straight to the backup without having to loop all the subfolders inside path A AGAIN (which take time).

Here is my batch:

@echo off

setlocal EnableDelayedExpansion

rem Script for backuping some subfolders from path A to path B

set BackupLocation=U:\Backup
set subfolder_no=1

FOR /F "delims=" %%a IN ('dir /b "Z:\Folder1\*"') DO ( 

    set subfolder=%%a

    if defined subfolder (
        echo !subfolder_no! !subfolder!
        set /a subfolder_no+=1
        
    )
    
)
    
set /a subfolder_no=%subfolder_no%-1
set /a index=0
set /a choice=-1

echo.
set /p choice=Enter the number(s) of the subfolder(s) you want to backup: 

FOR /F "delims=" %%a IN ('dir /b "Z:\Folder1\*"') DO ( 

    set subfolder=%%a

    if defined subfolder (
        set /a index+=1
    )

FOR %%f IN (%choice%) DO if %%f==!index! (

echo.
echo Backuping subfolder !subfolder!

xcopy "Z:\Folder1\!subfolder!" "%BackupLocation%\!subfolder!\" /e /i /y

)
)

echo.
pause

exit

How can I do this? Is it possible to get the subfolders' name from their matching number and store them in variables or something?

Thanks a lot for your help !

Here's an example which only enumerates the directories once.

Please note, whilst it technically answers your question, and performs the task you require of it, this version is designed to work as intended on Windows 10. The specific part you asked about works in other versions too, but the :BackUp labelled section uses a new and undocumented Windows 10 feature of the sort command, to return only unique items from the selection list. Without that, your end user could tehnically provide the same number multiple times, and thus trigger multiple backups of the same directory. As this part of the code is technically outside of the scope of your question, I will leave it up to you to modify the code section yourself, should you be deploying this on older Operating Systems.

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

Rem Script for backing up some subdirectories of a Source path to a Backup path.
Set "SourceLocation=Z:\Folder1"
Set "BackupLocation=U:\Backup"

If Not Exist "%Sourcelocation%\." Exit /B
If Not Exist "%Backuplocation%\." Exit /B

:ShowSet
For /F "Delims==" %%G In ('"(Set subdirectory[) 2>NUL"') Do Set "%%G="
Set "index=0"
For /F "EOL=? Delims=" %%G In ('Dir /B /A:D /O:N "%SourceLocation%" 2^>NUL'
) Do (Set /A index += 1
    Set "subdirectory=%%G"
    SetLocal EnableDelayedExpansion
    Echo !index! !subdirectory!
    For /F "Tokens=1,*" %%H In ("!index! !subdirectory!") Do (EndLocal
        Set "subdirectory[%%H]=%%I"))
If Not Defined subdirectory[1] Exit /B

:Select
Echo(
Echo Please type the number(s) for the subdirectories you want to backup,
Echo(
Echo For multiple selections please separate each with spaces e.g. 1 3 6
Echo For none please type 0 or press [ENTER].
Set "selection=0"
Set /P "selection=>"
Set "selection=%selection:"=%"
Set "selection=%selection:)=%"
If Not Defined selection GoTo Select
If "%selection%" == "0" GoTo :EOF
(Set selection) | "%SystemRoot%\System32\findstr.exe"^
 /X /R /C:"selection=[0123456789 ][0123456789 ]*" 1>NUL || GoTo Select
Set "selection=%selection% "

:BackUp
For /F %%G In (
    '"(Echo(%selection: =^&Echo(%) | "%SystemRoot%\System32\sort.exe" /Unique"'
) Do If Not Defined subdirectory[%%G] (Echo Selection %%G was not valid) Else (
    SetLocal EnableDelayedExpansion
    Echo(&Echo Backing up subdirectory %%G !subdirectory[%%G]!
    "%SystemRoot%\System32\Robocopy.exe" ^
     "%SourceLocation%\!subdirectory[%%G]!" ^
      "%BackupLocation%\!subdirectory[%%G]!" /E /NC /NDL /NJH /NJS /NS ^
       | %SystemRoot%\System32\find.exe /V " (0x00000005) "
    EndLocal)
Pause

In the :BackUp section, I have used Robocopy.exe instead of the deprecated xcopy.exe utility you had used .

If you wish to still use xcopy.exe , replace:

    "%SystemRoot%\System32\Robocopy.exe" ^
     "%SourceLocation%\!subdirectory[%%G]!" ^
      "%BackupLocation%\!subdirectory[%%G]!" /E /NC /NDL /NJH /NJS /NS ^
       | %SystemRoot%\System32\find.exe /V " (0x00000005) "

with:

    "%SystemRoot%\System32\xcopy.exe" ^
     "%SourceLocation%\!subdirectory[%%G]!" ^
      "%BackupLocation%\!subdirectory[%%G]!\" /E /I /Y

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM