批处理文件中如何迭代遍历文件夹和文件?

5
这是我的情况。一个项目的目标是将一些附件迁移到另一个系统。
这些附件将位于父文件夹中,假设为“Folder 0”(请参见this question's diagram以更好地理解),并且它们将被压缩/打包。
我希望我的批处理脚本被这样调用:
BatchScript.bat "c:\temp\usd\Folder 0"

我正在使用 7za.exe 作为命令行提取工具。

我想让我的批处理脚本遍历“Folder 0”的子文件夹,并将所有包含的 ZIP 文件解压到它们各自的文件夹中。

强制要求提取的文件与其相应的 ZIP 文件在同一个文件夹中。因此,“File 1.zip”中包含的文件需要在“Folder 1”中等等。

我已经阅读了关于 FOR...DO 命令的相关文献,参考了 Windows XP Professional Product Documentation - Using Batch Files

以下是我的脚本:

@ECHO OFF

FOR /D %folder IN (%%rootFolderCmdLnParam) DO 
    FOR %zippedFile IN (*.zip) DO 7za.exe e %zippedFile

我想在调用 7za.exe e %zippedFile 进行文件提取之前,也需要更改实际目录,但我无法在此批处理文件中找到方法(尽管我知道如何在命令行中执行,即使我知道它是相同的指令“cd”)。 编辑#1 我已经收到了一些关于ServerFault的提示,与同样的问题有关。请参见this link的答案。
然而,它从根目录(C:)提取,而不是从参数中给出的文件夹中提取。
有人有想法吗? 编辑#2 批处理脚本似乎不能很好地处理包含空格字符的文件夹和文件名。有人可以确认一下我的想法吗? 编辑#3

我需要它完全递归,因为我不知道将使用哪个目录结构。

编辑#4.a 使用@aphoria的解决方案,我已经接近成功了!唯一的问题是,它拿到一个名为File5.zip的文件后,只获取文件名File5,创建一个子文件夹File5并将File5.zip解压到File5子文件夹中,然后,它想要在Folder 1中创建一个File5子文件夹,而实际上应该创建一个File1子文件夹,以符合我的示例。

编辑 #4.b

按照要求,这里是代码的当前外观:

@echo off

setlocal enableextensions enabledelayedexpansion

rem
rem Display instructions when no parameter is given.
rem
if "%1" equ "" (
    echo Syntaxe : od.bat ^<directory mask>^
    echo Exemple : od.bat *
    goto :Eof
)

rem
rem Setting the PATH environment variable for this batch file for accessing 7za.exe.
rem
path=c:\temp;%PATH%

rem
rem Removing quotes from the given command line parameter path.
rem
set root=%1
set root=%root:~%1
set root=%root:~0,-1%

rem Searching directory structure from root for subfolders and zipfiles, then extracting the zipfiles into a subfolder of the same name as the zipfile.
for /F "delims==" %%d in ('dir /ogne /ad /b /s %root%') do (
    echo Traitement du dossier : "%%d"

    for /F "delims==" %%f in ('dir /b "%%d\*.zip"') do (
        rem Getting filename without extension.
        set subfolder=~n%f
        mkdir "%%d\%subfolder%"
        rem Extracting zipfile content to the newly created folder.
        7za.exe e "%%d\%%f" -o"%%d\%subfolder%"
    )
)

:Eof

endlocal

有什么想法吗?

我猜它一次只能挖掘一个目录层次。这里的情况是这样的:假设我们在Folder 1中有一个Folder A(Folder 1\Folder A),那么它会从Folder 1Folder 5进行搜索,然后返回到Folder 1\Folder A,其中%subfolder%变量保持其最后一个值。

非常感谢任何人的帮助。

1个回答

8

我对7zip命令行选项不是很熟悉,所以您需要找出确切的命令,但以下脚本将接受一个完全指定的路径(允许空格),并打印出该路径下的文件夹名称和.zip文件。

@ECHO OFF

REM
REM Remove the double quotes from the front and end of the root path
REM
SET ROOT=%1
SET ROOT=%ROOT:~1%
SET ROOT=%ROOT:~0,-1%
ECHO %ROOT%

FOR /F "DELIMS==" %%d in ('DIR "%ROOT%" /AD /B') DO ( 
  ECHO %%d
  FOR /F "DELIMS==" %%f in ('DIR "%ROOT%\%%d\*.zip" /B') DO (
    ECHO   %%f
  )
)  


按以下方式运行它:

MyScript.CMD "c:\temp\usd\Folder 0"

您应该得到类似于此的输出:

Folder A
  File 1.zip
  File 2.zip
Folder B
  File 1.zip
  File 2.zip  

更新

以下代码将提取Folder A\File 1.zip到一个新文件夹Folder A\File 1

需要注意以下几点:

  1. 在第一个FOR循环中,需要将%ROOT%用双引号括起来处理名称中带有空格的文件夹。
  2. 由于你在第二个FOR中使用了SET设置变量,因此需要在开头放置SETLOCAL ENABLEDELAYEDEXPANSION。然后,使用!(例如!subfolder!)强制在运行时进行扩展引用变量。
  3. 这一行代码set subfolder=~n%f应该是这样的set subfolder=%%~nf
  4. 我在MKDIR7za.exe命令前面加上了以进行测试。一旦确定它正在执行所需操作,就可以删除语句。

以下是代码:

@ECHO OFF

SETLOCAL ENABLEDELAYEDEXPANSION

REM
REM Remove the double quotes from the front and end of the root path
REM
SET ROOT=%1
SET ROOT=%ROOT:~1%
SET ROOT=%ROOT:~0,-1%
ECHO %ROOT%

REM Searching directory structure from root for subfolders and zipfiles,
REM then extracting the zipfiles into a subfolder of the same name as the zipfile.

FOR /F "delims==" %%d IN ('dir /ogne /ad /b /s "%ROOT%"') DO (
    ECHO Traitement du dossier : "%%d"

    FOR /F "delims==" %%f IN ('dir /b "%%d\*.zip"') DO (
        REM Getting filename without extension.
        SET subfolder=%%~nf
        ECHO mkdir "%%d\!subfolder!"
        REM Extracting zipfile content to the newly created folder.
        ECHO 7za.exe e "%%d\%%f" -o"%%d\!subfolder!"
    )
)

ENDLOCAL

谢谢您的回答!现在,为了使您的解决方案完全递归,我该怎么做? - Will Marcouiller
我们快成功了!感谢您和提供的解决方案!=)现在我唯一需要处理的是:>每次它必须解压缩Zip文件时,它总是想创建相同的子文件夹。请参见我的编辑。 =) - Will Marcouiller
我不确定我完全理解。您能否更新问题,将您的代码目前看起来是什么样子? - aphoria
@aphoria:我刚刚编辑了你的答案,以说明我所做的微小更改:“-o"%%d!subfolder!"”,而不是“-o"%%d%subfolder%"”。 - Will Marcouiller
@aphoria:感谢你对于的提示。我已经按照建议阅读了SET /?,现在我可以理解它的值将在运行时评估,如果我可以这样总结的话。这就是为什么它允许值变化的原因。确实,只有当启用了ENABLEDELAYEDEXPANSION时才有效。所以对我来说,这是新的功能!我曾经写过一些批处理文件,就在将近20年前的DOS 5.0时代。呵呵呵...谢谢朋友!=) - Will Marcouiller
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接