查找所有文件并复制到保留文件夹结构的另一个目标

时间:2016-01-06 07:45:42

标签: windows batch-file copy

我的文件夹结构中散布着一堆*.jpg个文件。

现在我想找到CSV文件中列出的一些文件(仅一列)或逐行找到文本文件,如

one.jpg  
ten.jpg  
five.jpg

并将所有这些*.jpg文件复制到另一个文件夹,保持文件夹结构如下:

outputfolder\somefolder\somefolder\one.jpg

outputfolder\somefolder\ten.jpg

outputfolder\somefolder\somefolder\somefolder\five.jpg

我怎样才能做到这一点?

这是我尝试过的

@echo off 
CLS 
REM CHECK FOR ADMIN RIGHTS 
COPY /b/y NUL %WINDIR%\06CF2EB6-94E6-4a60-91D8-AB945AE8CF38 >NUL 2>&1 
IF ERRORLEVEL 1 GOTO:NONADMIN 
DEL %WINDIR%\06CF2EB6-94E6-4a60-91D8-AB945AE8CF38 >NUL 2>&1 
:ADMIN 
REM GOT ADMIN RIGHTS 
COLOR 
1F ECHO Please wait... 
FOR /R "%~dp0" %%I IN (.) DO 
for /f "usebackq delims=" %%a in ("%~dp0list.txt") do 
echo d |xcopy "%%I\%%a" "C:\B2B_output_files" /e /i 
COLOR 2F 
PAUSE 
GOTO:EOF 
:NONADMIN 
REM NO ADMIN RIGHTS 
COLOR 4F 
pause 
GOTO:EOF 

2 个答案:

答案 0 :(得分:2)

Stack Overflow不是免费的代码编写服务,请参阅帮助主题What topics can I ask about here?

但是,我已经为此任务编写了整个批处理代码。从这个注释代码中学习,下次尝试自己编写批处理代码,并且只询问你是否坚持自己在几次试验后无法自行解决的问题,而不是在Stack Overflow或任何其他网站上找到解决方案。

必须在下面的批处理脚本的顶部定义源和目标基本文件夹的路径。

包含要逐行复制的文件名称的文本文件必须命名为FileNames.txt,并且必须使用下面的批处理代码存储在源基本文件夹中。

@echo off
setlocal EnableExtensions EnableDelayedExpansion

rem Define source and target base folders.

rem Note:

rem The paths should not contain an equal sign as then the
rem string substitutions below would not work as coded. The
rem target base folder can be even a subfolder of the source
rem base folder.

set "SourceBaseFolder=C:\Temp"
set "TargetBaseFolder=C:\Temp\OutputFolder"

rem Set source base folder as current directory. The previous
rem current directory is restored by command endlocal at end.

if not exist "%SourceBaseFolder%\*" (
    echo %~nx0: There is no folder %SourceBaseFolder%
    set "ErrorCount=1"
    goto HaltOnError
)

cd /D "%SourceBaseFolder%"

if not exist "FileNames.txt" (
    echo %~nx0: There is no file %SourceBaseFolder%\FileNames.txt
    set "ErrorCount=1"
    goto HaltOnError
)

rem For each file name in text file FileNames.txt in
rem source base folder the loops below do following:

rem 1. Search recursively for a file with current file name
rem    in entire directory tree of source base folder.

rem 2. If a file could be found, check its path. Skip the
rem    file if the path of found file contains the target
rem    folder path to avoid copying files to itself. This
rem    IF condition makes it possible that target base
rem    folder is a subfolder of source base folder.

rem 3. Create the folders of found file relative to source
rem    base path in target base folder. Then check if this
rem    was successful by verifying if the target folder
rem    really exists and copy the file on existing folder or
rem    output an error message on failure creating the folder.

set "ErrorCount=0"
for /F "usebackq delims=" %%N in ("FileNames.txt") do (
    for /R %%J in ("%%N*") do (
        set "FilePath=%%~dpJ"
        if "!FilePath:%TargetBaseFolder%=!" == "!FilePath!" (
            set "TargetPath=%TargetBaseFolder%\!FilePath:%SourceBaseFolder%\=!"
            md "!TargetPath!" 2>nul
            if exist "!TargetPath!\*" (
                echo Copying file %%~fJ
                copy /Y "%%~fJ" "!TargetPath!" >nul
            ) else (
                set /A ErrorCount+=1
                echo Failed to create directory !TargetPath!
            )
        )
    )
)

:HaltOnError
if %ErrorCount% NEQ 0 (
    echo.
    pause
)
endlocal

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

  • call /? ...有关%~nx0
  • 的说明
  • copy /?
  • echo /?
  • endlocal /?
  • for /?
  • goto /?
  • if /?
  • md /?
  • pause /?
  • rem /?
  • set /?
  • setlocal /?

另请阅读微软有关Using command redirection operators的文章,了解2>nul是否有效抑制写入 STDERR 的错误消息。

答案 1 :(得分:1)

以下代码应该按照您的要求执行:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "LISTFILE=copylist.txt"
set "SOURCE=.\source"
set "DESTIN=.\destin"
for /F "usebackq eol=| delims=" %%L in ("%LISTFILE%") do (
    for /F "eol=| delims=" %%F in ('
        cd /D "%SOURCE%" ^
            ^& xcopy /L /S /I /Y ".\%%~L*" "%TEMP%" ^
            ^| findstr /I /R "^\..*\\%%~L$"
    ') do (
        2> nul md "%DESTIN%\%%F\.."
        copy /B /-Y "%SOURCE%\%%F" "%DESTIN%\%%F"
    )
)
endlocal
exit /B

它依赖于xcopy输出相对路径到控制台的事实,如果给出了相对源路径,并且它具有一个开关/L,它告诉它不要复制任何东西,而是列出什么会没有开关就被复制。还有一个开关/S,它定义为在子目录中递归搜索源项。

虽然需要解决一个小问题:如果source包含通配符xcopy /S*?仅遍历子目录,但如果专用文件名是给出。这就是*附加到文件名的原因。由于这当然也可以匹配一些非预期的项目,findstr用于过滤它们。

所以基本上有一个for /F循环遍历文本文件copylist.txt中列出的项目。在此循环中,嵌套了另一个for /F,它枚举了上述findstr - 过滤的xcopy /L /S输出的输出,该输出一个接一个地接收外循环的项。嵌入式cd命令确保位于源目录中。 xcopy的目标只是一个现有目录,以避免错误消息(请记住,由于/L,实际上没有任何内容被复制)。

内循环bopy包含一个md命令,用于创建目标目录(树),如果不存在(2> nul可以避免错误消息,如果先前已经创建过),并且copy实际执行复制活动的命令;交换机/-Y定义为在目标位置已存在项目时提示用户,您可以将其更改为/Y以覆盖而不询问。