我是创建批处理文件的新手,希望有人可以帮助我。 我们的一位员工通过电子邮件收到压缩的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
名称以适合我的系统。
然后是输出目录。我调整了他们的名字以适应我的系统。请注意,批处理在很大程度上不区分大小写,因此设置Output8A
和Output8a
是设置相同的变量。批处理命令区分大小写的唯一时间是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
子句,因为默认分隔符包括空格,并且默认tokens
是1
,因此只有每行输出的第一个字符串直到第一个空格才会分配给%%a
。
嗯 - 你已经rem
for/r
了.遗憾的是,for /r
中的目标目录不能是元变量。
接下来,我清除了一个copied
标志,上面写着"到目前为止,此文件尚未复制">
接下来,将fichier
设置为文件名的仅名称部分。由于您使用.pdf
作为筛选器,因此for/f
输出的每个名称都将是一个完整的文件名,以.pdf
结尾
接下来,几乎正确使用if
语句的电池。该/i
使比较不区分大小写,以便它能够应对8a
和8A
。==
两侧的字符串必须相同才能通过==
测试,因此在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
文件的名称部分%%~na
到findstr
中,则设置为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 秒过后,它可能仍然存在于同一位置,并且将被无休止地复制和重新复制。您可能需要进行调整才能达到预期的结果。