Batch file 如何从dir调用循环中排除目录--比| find/v更快
现在我有一个批处理脚本,用于遍历一堆子文件夹,并压缩其中的日志文件,文件夹结构基本上如下所示:Batch file 如何从dir调用循环中排除目录--比| find/v更快,batch-file,for-loop,find,batch-processing,dir,Batch File,For Loop,Find,Batch Processing,Dir,现在我有一个批处理脚本,用于遍历一堆子文件夹,并压缩其中的日志文件,文件夹结构基本上如下所示: +---fakeG | +---ExclusionFolder | | +---LimitlessFolders | | +---MoreFolders | | \---SoManyFolders | +---logs1 | +---logs2 | +---logs3 | +---logs4 | +---logs5 | \---logs6 :DoZ
+---fakeG
| +---ExclusionFolder
| | +---LimitlessFolders
| | +---MoreFolders
| | \---SoManyFolders
| +---logs1
| +---logs2
| +---logs3
| +---logs4
| +---logs5
| \---logs6
:DoZip
:: Parameter 1 = Filename without .EXT for Archive Name
:: Parameter 2 = Target file specifics
:: Parameter 3 = Zip Command (Winzip/7zip64/7zip32)
:: Parameter 4 = Zip Parameters (a -tzip, -a)
:: Parameter 5 = ProcessLog
setlocal
SET archiveName=%~1
SET SourceFileSpec=%~2
SET zipCommand=%~3
SET zipParms=%~4
SET RunLog=%~5
ECHO %TIME% Archiving %SourceFileSpec%...
ECHO %TIME% Archiving %SourceFileSpec%... >> %RunLog%
ECHO "%zipCommand%" %zipParms% "%archiveName%.zip" "%SourceFileSpec%"
ECHO "%zipCommand%" %zipParms% "%archiveName%.zip" "%SourceFileSpec%" >> %RunLog%
"%zipCommand%" %zipParms% "%archiveName%.zip" "%SourceFileSpec%" >> %RunLog%
:: Check errorlevel of executed command
:: If errorlevel != 0, set EC with the errorlevel and echo that there was an error in archival
IF NOT %ERRORLEVEL%==0 (
ECHO ***ERROR archiving %SourceFileSpec% >> %RunLog%
SET EC=%ERRORLEVEL%
ECHO ***ERRORLEVEL RETURNED: %EC% >> %RunLog%
) ELSE (
:: Otherwise, delete the file
ECHO. >> %RunLog%
ECHO. >> %RunLog%
ECHO %TIME% Deleting %SourceFileSpec%...
ECHO %TIME% Deleting %SourceFileSpec%... >> %RunLog%
::Quietly delete the file
DEL /Q %SourceFileSpec%
:: Set ErrorLevel to capture the Delete command result.
SET EC=%ERRORLEVEL%
)
GOTO :EOF
必须遍历这些子文件夹中的每一个子文件夹,也必须遍历它们的子文件夹。此脚本必须避免使用一个特定的文件夹,它确实避免了它,但它使用了%| find/v。虽然在本例中,ExclutionFolder位于列表的顶部,但在真正的文件夹结构中,它不是
我现在是这样做的:
FOR /F "delims=" %%A IN (
'DIR "%LogsFilespec%" /B /S ^| find /v "ExclusionFolder"'
) DO CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%zipParams%" %ProcessLog%
在ExclutionFolder中,有更多的子文件夹,可能有更多的子文件夹,因此它会降低必须进入每个子文件夹的脚本执行速度
SO:有没有一种更快的方法可以在没有| find的情况下从dir调用中排除文件夹?
还是我必须想出一个完全不同的方法来做这件事
编辑抱歉,%LogsFileSpec℅ 引用目标文件。我最初的编辑是对的,第二次编辑是错的
SET LogsLocation="G:\fakeG\Data\Logs"
SET LogsName="trace*%targetDate%.log"
SET LogsFilespec="%LogsLocation%\%LogsName%"
很抱歉没有提供更多的脚本,我认为这个问题不需要太多
Edit2过程:DoZip的工作原理如下:
+---fakeG
| +---ExclusionFolder
| | +---LimitlessFolders
| | +---MoreFolders
| | \---SoManyFolders
| +---logs1
| +---logs2
| +---logs3
| +---logs4
| +---logs5
| \---logs6
:DoZip
:: Parameter 1 = Filename without .EXT for Archive Name
:: Parameter 2 = Target file specifics
:: Parameter 3 = Zip Command (Winzip/7zip64/7zip32)
:: Parameter 4 = Zip Parameters (a -tzip, -a)
:: Parameter 5 = ProcessLog
setlocal
SET archiveName=%~1
SET SourceFileSpec=%~2
SET zipCommand=%~3
SET zipParms=%~4
SET RunLog=%~5
ECHO %TIME% Archiving %SourceFileSpec%...
ECHO %TIME% Archiving %SourceFileSpec%... >> %RunLog%
ECHO "%zipCommand%" %zipParms% "%archiveName%.zip" "%SourceFileSpec%"
ECHO "%zipCommand%" %zipParms% "%archiveName%.zip" "%SourceFileSpec%" >> %RunLog%
"%zipCommand%" %zipParms% "%archiveName%.zip" "%SourceFileSpec%" >> %RunLog%
:: Check errorlevel of executed command
:: If errorlevel != 0, set EC with the errorlevel and echo that there was an error in archival
IF NOT %ERRORLEVEL%==0 (
ECHO ***ERROR archiving %SourceFileSpec% >> %RunLog%
SET EC=%ERRORLEVEL%
ECHO ***ERRORLEVEL RETURNED: %EC% >> %RunLog%
) ELSE (
:: Otherwise, delete the file
ECHO. >> %RunLog%
ECHO. >> %RunLog%
ECHO %TIME% Deleting %SourceFileSpec%...
ECHO %TIME% Deleting %SourceFileSpec%... >> %RunLog%
::Quietly delete the file
DEL /Q %SourceFileSpec%
:: Set ErrorLevel to capture the Delete command result.
SET EC=%ERRORLEVEL%
)
GOTO :EOF
编辑3这里是zipCommand
SET PathWinZip=C:\Program Files\WinZip\wzzip.exe
SET Path7Zip_64bit=C:\Program Files\7-Zip\7z.exe
SET Path7Zip_32bit=C:\Program Files (x86)\7-Zip\7z.exe
:: Check for WinZip
IF EXIST "%PathWinZip%" SET zipCommand=%PathWinZip% & SET zipParms=-a
:: Check for 32-bit version of 7-Zip. If found, configure
:: its command line parameter to produce a .zip file
IF EXIST "%Path7Zip_32bit%" SET zipCommand=%Path7Zip_32bit% & SET zipParms=a -tzip
:: Check for 64-bit version of 7-Zip. If found, configure
:: its command line parameter to produce a .zip file
IF EXIST "%Path7Zip_64bit%" SET zipCommand=%Path7Zip_64bit% & SET zipParms=a -tzip
这种方法可以快一点:
pushd "%LogsFilespec%"
rem get subfolders of first level only
for /f "tokens=*" %%p in (
'DIR "%LogsFilespec%" /B /AD ^| find /v "ExclusionFolder"'
) do (
rem treat each (here will not be excluded one)
FOR /F "delims=" %%A IN (
'DIR "%%~p" /B /S'
) DO CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%zipParams%" %ProcessLog%
)
popd
goto :eof
下面的解决方案不使用单个
FIND
命令,也不使用FOR/F…
命令(需要执行cmd.exe的副本),因此我认为它应该运行得更快:
@echo off
setlocal
rem Enter to the base folder
cd "%LogsFilespec%"
rem Start the recursive process
call :processThisDir
goto :EOF
:processThisDir
rem Process the files in this folder
for %%A in (*.*) do CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%zipParams%" %ProcessLog%
rem Process nested subfolders, but omit "ExclusionFolder"
for /D %%a in (*) do (
if "%%a" neq "ExclusionFolder" (
cd "%%a"
call :processThisDir
cd ..
)
)
exit /B
我认为以下内容应排除相关子树:
FOR /F "delims=" %%X IN (
'DIR /B /ad ') DO IF /i "%%X" neq "ExclusionFolder" FOR /F "delims=" %%A IN (
'DIR /B /S "%%X\%LogsFilespec%"'
) DO CALL :DoZip "%%~dpnA" "%%~fA" "%zipCommand%" "%zipParams%" %ProcessLog%
即,执行目标的目录名扫描;如果找到的目录不是排除名称,则对该子目录执行其余操作。是否可以使用比
%LogsFilespec%
更具体的表达式指定其他文件?例如,根据您显示的内容,它可以是,For/F。。。在('DIR%LogsFilesspec%/logs*'/B/S'…)…
或类似的东西中…不知道:DoZip
过程:一些压缩工具,可能大多数,允许使用文件列表或某种准脚本。创建这样的列表(一组特定列表)并调用自适应的:DoZipList
可能会更快?请显示所有变量的定义并显示:DoZip
例程,和/或更好地描述您尝试执行的操作。很可能有更好的方法来完成您的任务,但是您没有提供足够的信息。感谢您的回复!我正在尝试此解决方案,但获取的文件名、目录名或卷标语法不正确。
文件名、目录名或卷标语法不正确。
尝试在循环之前将CD刻录到目录,只需输出更多。我意识到我的CD中有一个输入错误。现在,它可以找到所有日志文件,包括那些不应该存档的文件,但它确实忽略了这个文件夹!但它实际上并没有存档或删除它们,它只是在DoZip中对它应该附加到%RunLog%的文本进行了响应……在这种情况下,问题应该出在DoZip
中。您似乎说所提供的参数与您预期的一样,因此该问题似乎与“排除目录”问题无关。由于您尚未发布什么是zipCommand
,我怀疑它一定是一个批处理文件,因此dozip
将把控制权转移到该批处理文件,而“%zipCommand%”之后的剩余部分将被跳过。请尝试调用“%zipCommand%”..
为dozip
提供返回位置。很抱歉,zipCommand只是脚本前面设置的一个变量。为了澄清,我编辑了我原来的帖子。我现在担心的是,我以前在本文档中遇到的一个问题再次浮出水面,那就是复杂的引号会弄乱zip命令行。。。。编辑:是的,正如我所怀疑的那样:正确的命令行显示如下:“C:\Program Files\7-Zip\7z.exe”a-tzip“C:\Users\me\Documents\fakeG\logs2\trace\u 20150217.Zip”“C:\Users\me\Documents\fakeG\logs2\trace\u 20150217.log”
,但现在输出中排除了a-tzip
。噢,天哪!我意识到zipParms
不起作用,因为你像普通人一样用zipParams
重写了我的DoZip调用,而我原来是zipParms
!!在拼图的最后一部分,这个脚本现在存档了每个日志,而不仅仅是那些遵循trace*%targetDate%.log的日志