如何使用批处理文件使用查找文件移动带有关键字的文件?

时间:2018-04-05 05:43:55

标签: batch-file

我有一个存储在文件夹中的CSV文件中的ID列表。然后我有包含这些ID的文件。如果文件存在于CSV文件中,我想移动文件。

例如:

我在Docs文件夹中有这些文件:Jose_1234_CV.pdfJose_111_CV.docJose_2323_CV.doc

我的IDs.csv文件包含以下ID:1234111

运行批处理作业时,应将ID为1234111的文件移动到特定文件夹。

只有在查找文件中包含确切的文件名时,我才能使用以下代码。即使它只找到ID,我希望它能正常工作:

@echo off
set "Source=C:\users\directory"
set "Target=C:\users\target"
set "FileList=C:\users\lookup\ID.csv"
echo/

if not exist "%Source%" echo Source folder "%Source%" not found & goto :Quit
if not exist "%FileList%" echo File list "%FileList%" not found & goto :Quit
2> nul md "%Target%"

for /F usebackq^ delims^=^ eol^= %%a in ("%FileList%") do (
    for /F "delims=" %%b in ('dir /B /S /A:-D "%Source%\%%a"') do (
        move "%%b" "%Target%"
    )
)

:Quit
echo/
echo Press the Space bar to close this window.
pause > nul

1 个答案:

答案 0 :(得分:0)

这可以通过以下批处理文件来完成:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "BaseDirectory=C:\Users"
set "Source=%BaseDirectory%\directory"
set "Target=%BaseDirectory%\target"
set "FileList=%BaseDirectory%\lookup\IDs.csv"
set "TempFile=%TEMP%\%~n0.tmp"

if not exist "%Source%\" echo Source folder "%Source%" not found. & goto Quit
if not exist "%Source%\*_*_CV.*" echo Folder "%Source%" does not contain any *_*_CV.* file. & goto Quit
if not exist "%FileList%" echo File list "%FileList%" not found. & goto Quit
md "%Target%" 2>nul
if not exist "%Target%\" echo Folder "%Target%" could not be created. & goto Quit

set "FileMoved=0"
del "%TempFile%" 2>nul

rem Create a copy of list file with each identifer surrounded by underscores
rem to make sure that on an identifier like 111 just the file with _111_ in
rem name and not with _2111_ or _1114_ in name is moved to target folder.
for /F "usebackq delims=" %%I in ("%FileList%") do echo _%%~I_>>"%TempFile%"

rem Move all files containing one of the identifiers in
rem temporary file in its file name to the target folder.
for /F "eol=| delims=" %%I in ('dir "%Source%\*_*_CV.*" /A-D-H /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /L /G:"%TempFile%" 2^>nul') do (
    move /Y "%%I" "%Target%\%%~nxI" >nul
    if not errorlevel 1 set /A FileMoved+=1
)

rem Delete the temporary file no longer needed.
del "%TempFile%"

rem Delete the target directory if being empty.
if %FileMoved% == 0 rd "%Target%" 2>nul

rem Inform user about number of moved files.
set "Plural_S=s"
if %FileMoved% == 1 set "Plural_S="
echo Moved %FileMoved% *.csv file%Plural_S% to "%Target%".

:Quit
endlocal
echo/
echo Press SPACE to close this window.
pause >nul

此批处理代码要求文件C:\Users\lookup\IDs.csv逐行包含标识符,如:

1234
111

第一个 FOR 命令创建IDs.csv的副本,其中包含以下行:

_1234_
_111_

第二个 FOR 在一个单独的命令进程中执行,该进程以cmd.exe /C的后台开始(=不可见)命令行:

dir "C:\Users\directory\*_*_CV.*" /A-D-H /B /S 2>nul | C:\Windows\System32\findstr.exe /L /G:"C:\Users\UserName\AppData\Local\Temp\BatchFileName.tmp" 2>nul

因此,没有控制台窗口的后台命令进程首先运行命令 DIR 输出

  • 由于/A-D-H(属性不是目录而未隐藏)
  • ,所有非隐藏文件
  • 匹配通配符模式*_*_CV.*
  • 由于/B只是文件名,所以
  • 采用裸格式 由于/S
  • 在指定目录及其所有子目录中
  • 完整路径也是因为/S
  • 处理 STDOUT

DIR 如果找不到与通配符模式匹配的文件,则会输出错误消息。写入处理 STDERR 的错误消息会被2>nul重定向到设备 NUL ,从而抑制此消息。

DIR 的完整路径输出文件名逐行处理 STDOUT 会被重定向到|以处理 STDIN 下一个命令 FINDSTR

FINDSTR 搜索

的文件名列表
  • /G:
  • 之后指定的临时文件中列出的任何字符串 由于使用/I
  • 区分大小写
  • ,字面意思是因为使用了/L
  • 并输出包含临时文件中的一个字符串的行(=带有完整路径的文件名)。

这意味着文件路径中的目录不应包含_ID_,否则移动的文件不包含文件名中的标识符,而是包含在其路径中。

FINDSTR 可能无法找到符合搜索条件的任何行,因此会输出错误消息以处理 STDERR ,该消息通过重定向来抑制2>nul设备 NUL

命令 FOR 捕获为处理背景命令进程的 STDOUT 而编写的输出,该进程是 DIR 的输出,用过滤FINDSTR 然后逐行处理此输出。

FOR 会忽略空行。但这并不重要,因为每个带有完整路径的文件名列表都不包含空行。

FOR 也会忽略以分号开头的行,但是使用eol=|修改此行为以忽略以竖线开头的行。这里不能使用垂直条,因为没有目录或文件可以在名称中包含垂直条。好吧,具有完整路径的文件名实际上也不可能以分号开头。所以这里不需要eol=|

带有参数/F

FOR 默认情况下使用空格和水平制表符作为字符串分隔符划分为子字符串,并仅将第一个空格/制表符分隔的字符串分配给指定的循环变量{{ 1}}。这里不需要这种拆分行为,因为在 FOR 的正文命令块中需要始终是要在路径上移动的文件的完全限定名称,或者文件名包含空格字符。因此,I被指定用于定义一个空的分隔符列表,这些分隔符禁止将行拆分为子字符串。

执行

MOVE 会移动文件,并在成功时以delims=退出,并在出错时使用任何值0退出。

已执行的应用程序或命令的退出代码由Windows命令解释程序分配给环境变量0

IF 条件检查移动退出且值大于或等于 ERRORLEVEL ,即用1(或负值)取得成功。在这种情况下,文件已成功移动,相应的计数器增加了一个。

如果源目录中包含never子目录,那么最好使用第二个 FOR 循环:

0

DIR 此处没有for /F "eol=| delims=" %%I in ('dir "%Source%\*_*_CV.*" /A-D-H /B 2^>nul ^| %SystemRoot%\System32\findstr.exe /L /G:"%TempFile%" 2^>nul') do ( move /Y "%Source%\%%I" "%Target%\%%I" >nul if not errorlevel 1 set /A FileMoved+=1 ) ,因此输出是与没有路径的通配符模式匹配的非隐藏文件。因此, FINDSTR 仅在/S的文件名中进行搜索。命令 MOVE 必须包含_ID_,因为%Source%\在这种情况下只是没有路径的文件的名称。

要了解使用的命令及其工作原理,请打开命令提示符窗口,执行以下命令,并完全阅读为每个命令显示的所有帮助页面。

  • %%I
  • del /?
  • dir /?
  • echo /?
  • endlocal /?
  • findstr /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • move /?
  • pause /?
  • rd /?
  • rem /?
  • set /?

另请阅读Microsoft有关Using Command Redirection Operators的文章,了解setlocal /?2>nul的说明。重定向操作符|>必须使用 FOR 命令行上的插入符|进行转义,以便在Windows命令解释程序处理此命令行时将其解释为文字字符在执行命令 FOR 之前,它在后台启动的单独命令进程中执行嵌入式命令行。