首页 > 解决方案 > 批处理如何避免相同的第二个 FOR 循环?

问题描述

标签: windowsfor-loopbatch-filemultiple-choice

解决方案


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

推荐阅读