从具有许多子目录的主目录中批量提取特定文件类型

Batch extracting specific file types from master directory with many subdirectories

我有一些带有存档文件的文件夹, 包含子文件夹的父文件夹,例如

图形:

等 每个文件夹都包含一个存档 - 各种名称和编号。 每个档案包含各种文件,pdf 的 txt 文件发票和图像文件。 图片一般都是.jpg 命名各种名字。

我想做的是批量攻击父文件夹,从每个子目录的每个存档中提取图像 file/s,并将图像保留在其来源存档所在的子目录中。如果存档有多个图像也没关系,我不会针对单个特定图像。

希望以类似

的方式结束

图形:

如果可能的话,我宁愿避免提取所有分离图像的文件,然后不得不重新存档。

原来我尝试发现的是将图片文件批量解压到它所属的目录,将图片文件重命名为它的目录名。我没有接近解决方案,所以我认为如果可能的话,只提取图像就可以了,我可以使用重命名应用程序来做其他事情我发现批量重命名实用程序在我开始思考后就可以了它。 你不会想到,这么多年,你收集了这么多档案,像小水滴,最后变成了大海。

我已经尝试研究堆栈并看到了很多关于 7zip 如何工作的例子,但我就是无法完全理解它。

我即将退休,他们告诉我 65 岁是鸡舍的时间,我在 gfx 行业的大部分时间里都是推铅笔和滑鼠标的。我曾经知道每个档案中都有什么,但记忆有点……现在已经生锈了,我知道我所有的档案中都有图像。在日落时分,我的生活会轻松很多,只要看看这些照片,就不必绞尽脑汁去回忆档案中的内容。

澳大利亚殖民地提前祝贺和打招呼。

脾气暴躁

要回答你的问题,任务很简单,涉及 For 递归循环,但是为了稳健,解决方案将很复杂,不知道这些特定的长期可能如何混合,7zip 文件被细分,因此如果7zip 本身有两个子文件夹,其中包含相同名称的文件,您将遇到错误情况。我允许在必要时使用 -aou 自动重命名。但是我没有为每个文件添加文件夹名称,因为这是一个额外的步骤。

@echo off & Title Extract Images from 7z files
set "extractor=C:\Program Files (x86)-Zipz.exe"
set "archives=*.7z"
set "filetypes=*.png *.jpg *.jpeg *.tif *.tiff"
set "startDir=C:\Users\WDAGUtilityAccount\Desktop"

FOR /R "%startdir%" %%I IN (%archives%) DO ( "%extractor%" e "%%I" -o"%%~dpI" %filetypes% -aou)

您可以添加额外的存档类型,例如 .rar 或 .zip,就像我允许不同的图像文件类型一样。但是,首先要测试此类变化,否则第二个 运行 将调用现有重复项的自动命名。 您当然可以将 -aou 更改为 -aos 以避免覆盖或根据需要将其删除.

windows 的另一种方法是,可以导航标准 windows.zip 文件,从而将其保存为压缩文件夹,单击每个文件都会在默认应用程序中打开。因此,当您希望使用非默认应用程序时,只需提取到文件夹即可。

与您的需求更直接相关的次要优势是,一些观众可以只阅读图像而忽略任何其他内容(即使他们可以阅读文本或 html),我支持的一个是阅读图像zips 是 SumatraPDF,虽然没有列出,但它可以打开 .7Z 文件以相同的方式显示

因此我对提出的问题的回答是我建议将 7zip 转换为标准 zip 而不是扩展它们,或者使用 SumatraPDF 作为 default/alternative 7z 查看器!!

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION 
rem The following settings for the source directory, destination directory, target directory,
rem batch directory, filenames, output filename and temporary filename [if shown] are names
rem that I use for testing and deliberately include names which include spaces to make sure
rem that the process works using such names. These will need to be changed to suit your situation.

SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "outfile=%destdir%\outfile.txt"

SET "extensions=bat txt"
SET "archives=7z zip"

CALL :prefix sdexts *. %extensions%
CALL :prefix sdarchives *. %archives%
CALL :prefix dexts . %extensions%
CALL :prefix darchives . %archives%

PUSHD "%sourcedir%"

(
FOR /f "delims=" %%b IN ('dir /b /s /a-d %sdexts% %sdarchives%') DO (
 SET "unreported=%%b"
 FOR %%o IN (%darchives%) DO IF /i "%%~xb"=="%%o" CALL :procarch%%o&SET "unreported="
 IF DEFINED unreported ECHO %%~dpb ^| %%~nxb
)
)>"%outfile%"

popd

GOTO :EOF

:: return %1 with each other argument preceded by '%2'

:prefix 
SET "=%1="
shift
SET "=%~1"
:sdl
SHIFT
IF "%1"=="" SET "%%"&GOTO :eof
SET "=%% %%%1"
GOTO sdl

:: Process .7z or .zip archives

:procarch.7z
:procarch.zip
SET "skipme=Y"
FOR /f "delims=" %%e IN ('7z L "%unreported%"') DO (
 FOR /f "tokens=3delims= " %%o IN ("%%e") DO (
 IF "%%o"=="------------" (
  IF DEFINED skipme (SET "skipme=") ELSE (SET "skipme=Y")
 ) ELSE IF NOT DEFINED skipme ECHO "%%o"|FIND "D" >NUL &IF ERRORLEVEL 1 (
  SET "filename=%%e"
  FOR /f "delims=" %%y IN ("!filename:~53!") DO (
   FOR %%c IN (%dexts%) DO IF /i "%%c"=="%%~xy" ECHO %unreported% ^| %%y
  )
  )
 )
)

GOTO :eof

我也有类似的需求,所以我在这上面花了点时间...

第一部分只是设置要使用的目录。

我使用 battxt 作为测试所需的扩展。根据需要更改 - 只是一个 space-separated 列表。

同样,我选择检查 .zip.7z 档案。由于 7zip 可以处理两者,因此可以使用相同的子程序来处理两者。其他存档类型可能需要不同的处理。

该代码使用 dir 来定位感兴趣的文件,并且 dir 可以采用一系列参数,因此例程 :prefix 将作为 %3+ 提供的列表转换为变量 %1 中的列表,每个术语都以 %2 处的字符串为前缀。

所以 - 例如 sdexts 将变为 *.bat *.txtdexts .bat .txt

接下来,切换到源目录开始dir列出所需的文件。对于 %%b 中返回的每个名称(delims= 应用全名,/b 基本列表(仅名称),/s 处理子目录,/a-d 抑制目录名称)-标志 unreported 设置为找到的文件名,然后将找到的文件名的扩展名与 darchives 列表进行比较。如果找到匹配项,则执行 procarch%%o 例程并将 unreported 标志设置为 empty。然后,如果unreported还没有被清除,那就不是归档文件,所以报错。

procarch%%o 将解析 procarch.7zprocarch.zip 并提供例程(实际上是相同的例程)。

:prefix 例程将 </code> 设置为 <code>%1=,例如 sdexts=。然后它移动参数列表并将 </code> 设置为要放在每个术语之前的前缀。</p> <p>然后再换班。如果 <code>%1 不为空,则将 space 和 </code> 和 <code>%1 中的前缀附加到 </code> 并重复。</p> <p>当<code>%1变为空时,执行命令set "%%" and finish, so as $1would then contain the stringsdexts= *.bat *.txt, sdexts`将设置为所需的列表.

例程:procarch.7zprocarch.zip(第一个只是falls through到第二个,所以执行相同的处理)设置标志skipme为non-empty 因为我们需要跳过 7z 的 header 数据。

%%e依次获取7z L报表的每一行。 %%o 分配给 7z 报告行的第三个标记。这将是垃圾到带有一系列破折号的行,然后是归档项目的属性报告,然后是另一系列破折号,然后是垃圾。

所以 - 如果 %%o 是一串破折号,只需将 skipme 切换为空的 empty/not。

如果 %%o 不是破折号,并且 skipme 未定义,那么我们位于破折号的两行之间(即在归档项目行上),所以我们看是否 %%o 包含 D(这表明这是一个我们不想报告的目录名称)。如果没有,errorlevel 将由 find 设置 non-zero(find 的输出发送到 nul=aether)filename 设置为完整的报告行。我们对前 54 个字符不感兴趣,但其余部分包含存档文件名,因此请查看找到的文件名的扩展名是否是感兴趣的(在 dexts 中),如果是,请报告。

for ... %%b 之前的行中的 ()>"%outfile%" 相匹配,并将所有输出发送到名为.

的文件,否则将转到控制台

并且 echo 行上的 ^| 输出文字 | 字符,因为 |cmd 的特殊字符,需要 escaped^ 解释为文字。

我找到了问题的解决方案,无需编码,只需使用我已使用多年的应用程序即可。总指挥官。

最终解决方案很简单。

我打开 Total Commander,搜索我想要的存档文件 Alt F7 它会在右侧框架中列出我所有的存档文件 .7z .zip 无论你有什么。

然后您 select 在右下角找到“馈送至列表框”。按 Ctrl A 然后按 Alt F9,这会为您提供一些选项。

您清除压缩包中的特定文件以“确保其为空白”,然后要解压缩的文件告诉它您在我的情况下要寻找什么 .jpg(它可以是任何特定文件)。

如果与文件一起存储,请取消选中解压路径名 勾选或取消勾选覆盖现有文件 取消勾选将每个档案解压到一​​个单独的子目录(档案的名称) 点击确定。

然后它将搜索并找到您正在寻找的 file/s 并将它们解压缩到它们所在的 directory/subdirectory/etc 中。

工作完成...无需编码,只需使用 TC.. 很棒的应用程序