批量解压缩子文件夹中的文件,然后根据文件名中的数字将特定文件复制到网络文件夹



我是创建批处理文件的新手,希望有人可以帮助我。 我们的一位员工通过电子邮件收到压缩的pdf文档,她将其复制到桌面上的文件夹中。 在该文件夹中,我希望她运行一个批处理脚本,该脚本将

一个。 将压缩的内容解压缩到网络目录中,即\服务器\合约 在此目录下,进程将为每组合约创建文件夹,即 \server\contracts\Masterson(其名称将与压缩文件名相同)。

二. 然后,批处理应根据文件名将选定的几个 pdf 文档复制到网络目录中。 每个文件都包含一个数字,该数字将按以下方式排列:Masterson + 1.pdf>>\server\contracts\Item1和\server\contracts\Item2等。 Masterson + 1.pdf 将进入没有文件夹名称的 \server\contracts\Item1,Paisley + 1 证书.pdf Johnsonville + 1 document.pdf也是如此。

问题是公司不遵循说明,数字可以位于文件名的开头、中间或结尾。 此外,不幸的是,压缩文件和 pdf 文档的名称中有空格。 目前,我们仅将 4 个文件名复制到单独的目录中,供其他人查看和验证。

以下是我到目前为止环顾这个网站所做的:

@Echo off
SETLOCAL
for /R "delims=\servercontractsRECEIVED 2017-18 APPLICATION" %%I in   
("*.zip") do (
"%ProgramFiles(x86)%7-Zip7z.exe" x -y -o"%%~dpnI" "%%~fI" 
)

rem setlocal enableextensions disabledelayedexpansion
CLS
::The Input Folder
set "InputFolder=C:Userseartha.kittDesktopTest"
::The Output Folders
set "Output1=\servercontractsITEM 1 17-18 CERTS"
set "Output6=\servercontractsITEM 6 SIGNATURES"
set "Output8A=\servercontractsITEM 8A 17-18 CALENDARS"
set "Output8B=\servercontractsITEM 8B 16-17 REVISED CALENDARS"
set "Output8a=\servercontractsITEM 8A 17-18 CALENDARS"
set "Output8b=\servercontractsITEM 8B 16-17 REVISED CALENDARS"
::The extensions to wait
set "extensions=*.pdf"
setlocal EnableDelayedExpansion
:Loop
cls
echo Waiting for file ...
for /f "usebackq delims=|" %%a in ('dir /b /s %InputFolder%%extensions%  
2^>nul') do (
rem for /r %%a in in (%InputFolder%%extensions% 2^>nul') do (
set "Fichier=%%a"
echo Treating _^> %%a
if "!Fichier:~0,-2!"==" 1" COPY "%%~a" %Output1%
if "!Fichier:~0,-2!"==" 6" COPY "%InputFolder%~%%a" %Output6%
if "!Fichier:~0,-3!"=="8A" COPY "%InputFolder%%%a" %Output8A%
if "!Fichier:~0,-3!"=="8B" COPY "%InputFolder%%%a" %Output8B%
if "!Fichier:~0,-3!"=="8a" COPY "%InputFolder%%%a" %Output8a%
if "!Fichier:~0,-3!"=="8b" COPY "%InputFolder%%%a" %Output8b%
::Waiting ~5 seconds
ping localhost -n 6 >nul
)
::Return to the loop
goto:Loop

当然,这是行不通的。 请帮忙!

好吧 - 为尝试喝彩!这么近...

让我们看第一部分

for /R "delims=\servercontractsRECEIVED 2017-18 APPLICATION" %%I in ("*.zip") do (
"%ProgramFiles(x86)%7-Zip7z.exe" x -y -o"%%~dpnI" "%%~fI" 

)

这里的问题是delims子句只能在for /f中使用。for /r始终将整个文件名传递给元变量%%I

在我的系统上,我使用%server%u进行测试 -u是服务器上分配给U:的共享资源server.

for /R "\%server%ucontractsRECEIVED 2017-18 APPLICATION" %%I IN ("*.zip") do (
"%ProgramFiles(x86)%7-Zip7z.exe" x -y -o"%%~dpnI" "%%~fI" 

为我愉快地工作 - 将提取的文件交付给"u:\contracts\收到 2017-18 应用程序">

代码的第二部分是检查"C:\Users\eartha.kitt\Desktop\Test"而不是"\%server%\u\contracts\RECEIVED 2017-18 APPLICATION" - 非常明智地分配给变量名以便于调整。

这是我修改后的代码:

SET "terminatefilename=stop.txt"
DEL "%terminatefilename%" 2>nul
rem setlocal enableextensions disabledelayedexpansion
CLS
::The Input Folder
set "InputFolder=C:Userseartha.kittDesktopTest"
set "InputFolder=\%server%ucontractsRECEIVED 2017-18 APPLICATION"
::The Output Folders
set "Output1=\%server%ucontractsITEM 1 17-18 CERTS"
set "Output6=\%server%ucontractsITEM 6 SIGNATURES"
set "Output8A=\%server%ucontractsITEM 8A 17-18 CALENDARS"
set "Output8B=\%server%ucontractsITEM 8B 16-17 REVISED CALENDARS"
FOR /f "tokens=1*delims==" %%b IN ('set output') DO MD "%%c" 2>nul
::The extensions to wait
set "extensions=*.pdf"
setlocal EnableDelayedExpansion
:Loop
cls
echo Waiting for file ...
for /f "delims=|" %%a in ('dir /b /s "%InputFolder%%extensions%" 2^>nul') do (
rem for /r %%a in in (%InputFolder%%extensions% 2^>nul') do (
SET "copied="
echo Treating _^> %%a
REM OPTION 1 - Key string must be at end-of name part
set "Fichier=%%~Na"
if /i "!Fichier:~0,-2!"==" 1" COPY "%%a" "%Output1%"&SET "copied=Y"
if /i "!Fichier:~0,-2!"==" 6" COPY "%%a" "%Output6%"&SET "copied=Y"
if /i "!Fichier:~0,-3!"==" 8A" COPY "%%a" "%Output8A%"&SET "copied=Y"
if /i "!Fichier:~0,-3!"==" 8B" COPY "%%a" "%Output8B%"&SET "copied=Y"
REM OPTION 2 - Key string may be anywhere in filename
IF NOT DEFINED copied (
echo "%%~na"|FINDSTR /i /L /C:" 8B" >NUL
IF NOT ERRORLEVEL 1 COPY "%%a" "%Output8B%"&SET "copied=Y"
)
IF NOT DEFINED copied (
echo "%%~na"|FINDSTR /i /L /C:" 8A" >NUL
IF NOT ERRORLEVEL 1 COPY "%%a" "%Output8A%"&SET "copied=Y"
)
IF NOT DEFINED copied (
echo "%%~na"|FINDSTR /i /L /C:" 6" >NUL
IF NOT ERRORLEVEL 1 COPY "%%a" "%Output6%"&SET "copied=Y"
)
IF NOT DEFINED copied (
echo "%%~na"|FINDSTR /i /L /C:" 1" >NUL
IF NOT ERRORLEVEL 1 COPY "%%a" "%Output1%"&SET "copied=Y"
)
)

::Waiting ~5 seconds
timeout 6 >NUL
:: Test for exit
IF EXIST "%terminatefilename%" DEL "%terminatefilename%"&GOTO :EOF 
::Return to the loop
goto:Loop

首先,我设置了terminatefilename,以便创建此文件将终止批处理(这是代码中的无限循环设计)

接下来,我覆盖了您的inputfolder名称以适合我的系统。

然后是输出目录。我调整了他们的名字以适应我的系统。请注意,批处理在很大程度上不区分大小写,因此设置Output8AOutput8a是设置相同的变量。批处理命令区分大小写的唯一时间是for语句中的元变量(循环控制变量)。

然后我插入了一行来创建目标目录。这将使用set命令以Output1=\%server%ucontractsITEM 1 17-18 CERTS格式列出以output开头的变量(server已解析)。该命令读取set命令的输出,使用=作为分隔符,并将output1分配给%%b,将\%server%ucontractsITEM 1 17-18 CERTS分配给%%c。我们希望确保目录%%c存在,因此我们使用md命令进行制作,并忽略2>nul中已经存在的抱怨。

接下来是for/f.for /f读取(thisfilename)("this literal value")('the output of this command')的每一行,但是当您需要从名称必须用双引号括起来的文件中读取 时,因为它包含空格,则语法是for /f "usebackq"...(idontknow)("this filename containing spaces")('ive no idea whatever')或("此命令的输出")

所以没有必要使用usebackq- 事实上,它会适得其反。

delims=|是可选的,可以用delims=替换,因为dir命令的输出永远不会包含|(在文件或目录名中是非法的)。但是,您确实需要delims子句,因为默认分隔符包括空格,并且默认tokens1,因此只有每行输出的第一个字符串直到第一个空格才会分配给%%a

嗯 - 你已经remfor/r了.遗憾的是,for /r中的目标目录不能是元变量。

接下来,我清除了一个copied标志,上面写着"到目前为止,此文件尚未复制">

接下来,将fichier设置为文件名的仅名称部分。由于您使用.pdf作为筛选器,因此for/f输出的每个名称都将是一个完整的文件名,以.pdf结尾

接下来,几乎正确使用if语句的电池。该/i使比较不区分大小写,以便它能够应对8a8A==两侧的字符串必须相同才能通过==测试,因此在8测试中需要一个 3 个字符的字符串。

您显然一直在试验copy命令并尝试为其提供适当的字符串。%%~a去除%%a任何附上引号。%%a不会有括起来的引号 - 只有完整的文件名,所以在这种情况下这没有任何作用。%InputFolder%~%%a连接来自InputFolder、"\~" 和%%a的值 - 这意味着"%inputfolder%\~%inputfolder%\filenameand扩展名 %%a"。最后两个将解析为相同,除了~.

由于整个文件名都包含在%%a中,源文件所需要的只是"%%a"- 引用,因为它可能包含空格。

好吧 - 目标目录(我们已经用for /f...%%b建立了它)也可以包含空格,所以它也需要用引号引起来。

然后,我将标志copied设置为Y该行是否生效。实际上,它可以设置为任何非空值,因为整个对象是使用if defined语句解释它是否存在,以绕过以后复制同一文件的任何尝试(请记住 -copied为每个文件清除

)现在 - 第二个选项。这实际上是比子字符串版本更强大的所需目标字符串检测器,并且可以检测文件名中任何位置的目标字符串。

如果echo文件的名称部分%%~nafindstr中,则设置为findstr以查找不区分大小写c:"some literal string"/i/L文字字符串,并将 ny 匹配项输出到无处(>nul),则findstr会将errorlevel设置为0(如果找到),否则1。(这里的/L是多余的,我习惯性地使用它来提醒我我正在使用文字字符串,而不是正则表达式)

如果errorlevel当前为n或大于n,则If errorlevel n为 true,因此如果找到字符串,我们将像以前一样进行复制并设置copied标志。

我颠倒了测试的顺序,因为使用我使用的编辑器对我来说更容易。

现在 - 这种方法有一个缺点。这是一把双刃剑。由于在文件名中出现的任何位置都会检测到目标字符串,因此whatever whatever 10 something something.pdf将通过1测试,因为空格1 出现在其名称中。

循环完成后,使用timeout等待,将输出重定向到nul以使其向下管道。请注意,您的延迟在for循环内 - 因此它会在处理每个文件后等待 6 秒,而不是在处理整个批处理后等待 6 秒。

最后,如果您从另一个cmd实例创建terminatefilename,批处理将干净地退出并为您杀死terminatefilename。比对照-c干净得多。

最后一点:由于您正在copy文件,而不是MOVE它,因此在 6 秒过后,它可能仍然存在于同一位置,并且将被无休止地复制和重新复制。您可能需要进行调整才能达到预期的结果。

最新更新