批量解压缩子文件夹中的文件,然后根据文件名

时间:2017-04-04 01:38:51

标签: batch-file

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

的批处理脚本

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

B中。然后,批处理过程应根据文件名将选定的几个pdf文档复制到网络目录中。每个文件都包含一个数字,它将按以下方式进行:Masterson + 1.pdf>> \ server \ contracts \ Item1和\ server \ contracts \ Item2等.Masterson + 1.pdf将进入\ server \ contracts \ Item1而没有文件夹名称,Paisley + 1 certificate.pdf和Johnsonville + 1 document.pdf 。

问题是公司没有按照说明操作,编号可以在文件名的开头,中间或末尾。此外,遗憾的是,压缩文件和pdf文档的名称中还有空格。目前,我们只将4个文件名复制到单独的目录中供其他人查看和验证。

以下是我到目前为止看到的网站:

@Echo off

SETLOCAL
for /R "delims=\\server\contracts\RECEIVED 2017-18 APPLICATION" %%I in   
("*.zip") do (
"%ProgramFiles(x86)%\7-Zip\7z.exe" x -y -o"%%~dpnI" "%%~fI" 
)


rem setlocal enableextensions disabledelayedexpansion
CLS

::The Input Folder
set "InputFolder=C:\Users\eartha.kitt\Desktop\Test"

::The Output Folders
set "Output1=\\server\contracts\ITEM 1 17-18 CERTS"
set "Output6=\\server\contracts\ITEM 6 SIGNATURES"
set "Output8A=\\server\contracts\ITEM 8A 17-18 CALENDARS"
set "Output8B=\\server\contracts\ITEM 8B 16-17 REVISED CALENDARS"
set "Output8a=\\server\contracts\ITEM 8A 17-18 CALENDARS"
set "Output8b=\\server\contracts\ITEM 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

当然这不起作用。请帮忙!

1 个答案:

答案 0 :(得分:0)

嗯 - 勇敢的尝试!如此接近......

让我们来看第一部分

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

这里的错误是delims子句仅在for /f中可用。 for /r始终将整个文件名传递给元变量%%I

在我的系统上我使用%server%\u进行测试 - u是分配给U:\server的服务器上的共享资源。< / p>

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

为我愉快地工作 - 将提取的文件提供给&#34; u:\ contracts \ RECEIVED 2017-18 APPLICATION&#34;

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

这是我修改过的代码:

SET "terminatefilename=stop.txt"

DEL "%terminatefilename%" 2>nul
rem setlocal enableextensions disabledelayedexpansion
CLS

::The Input Folder
set "InputFolder=C:\Users\eartha.kitt\Desktop\Test"
set "InputFolder=\\%server%\u\contracts\RECEIVED 2017-18 APPLICATION"

::The Output Folders
set "Output1=\\%server%\u\contracts\ITEM 1 17-18 CERTS"
set "Output6=\\%server%\u\contracts\ITEM 6 SIGNATURES"
set "Output8A=\\%server%\u\contracts\ITEM 8A 17-18 CALENDARS"
set "Output8B=\\%server%\u\contracts\ITEM 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命令列出以output格式开始Output1=\\%server%\u\contracts\ITEM 1 17-18 CERTS的变量(其中server将被解析)。该命令读取set命令的输出,使用=作为分隔符,并将output1分配给%%b,将\\%server%\u\contracts\ITEM 1 17-18 CERTS分配给%%c。我们希望确保目录%%c存在,因此我们使用md命令进行操作,并忽略2>nul已存在的投诉。

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

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

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

嗯 - 你rem中了for/r。遗憾的是,for /r中的目标目录不能成为元变量。

接下来,我已经清除了一个copied标记&#34;到目前为止,此文件尚未被复制&#34;

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

结尾

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

您显然正在尝试使用copy命令并尝试使用适当的字符串来提供它。 %%~a剥离任何封闭引号的%%a%%a没有包含引号 - 只是整个文件名,所以在这个实例中什么都不做。 %InputFolder%\~%%a汇总来自InputFolder,&#34; \〜&#34;的值和%%a - 表示&#34;%inputfolder%\〜%inputfolder%\ filenameandextension of %% a &#34;。最后两个将被解析为相同,禁止~

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

嗯 - 目标目录(我们已经使用for /f...%%b建立了它)也可以包含空格,因此也需要引用它。

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

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

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

如果errorlevel当前为n或大于n,则

copied为真,因此如果找到该字符串,我们会复制并设置{{1}以前的标志。

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

现在 - 这种做法存在不利因素。这是一把双刃剑。由于检测到目标字符串它出现在文件名中,whatever whatever 10 something something.pdf将通过1的测试,因为 Space 1出现在其名称中。

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

最后,如果您从其他terminatefilename实例创建cmd,批处理将会干净地退出并为您杀死terminatefilename。比control-c更清洁。

最后一点:由于你是copy文件,而不是MOVE它,它可能仍然存在于同一个地方,大概是在6秒过后,将被无休止地复制和重新复制。您可能需要进行调整才能达到预期效果。