Search code examples
windowsbatch-filecopy

Copy multiples files listed in a text file from source subfolders to a new folder


I need to find a number of 500 image files, of which names I have listed in a text file (a single filename per line). The search is to be done in all subfolders of an external HDD and all files are to be copied to local drive.

pushd D:\move_script
for /f "tokens=* delims=" %%a in ('type List.txt') do xcopy /hrkvy ".\SourceFolder\%%a" ".\DestinationFolder"
popd

Files not found in SourceFolder.There are multiple subfolders in directory D:\move_script So how i mentioned the sourcefolder so that it can search files in all subfolders under D:\move_script .

When i use the single sourcefolder like in the below command then its searched files only under data folder and copied to destination folder.

for /f "tokens=* delims=" %%a in ('type List.txt') do xcopy /hrkvy ".\**data**\%%a" ".\DestinationFolder"

Please help what is wrong for search source subfolders.


Solution

  • AIUI, the problem is to copy the files named in the list.txt file from wherever they exist in the source subtree to the destination directory.

    An issue with your code: You have used a pushd/popd bracket, which means that between the pushd and the popd, the current directory is (the argument to the PUSHD)

    The . in the term ".\SourceFolder\%%a" means the directory relative to the current directory - and the current directory is D:\move_script, so the source interpreted by xcopy is "D:\move_script\SourceFolder\%%a"

    The easy way to fix this is to remove the pushd/popd commands, and execute
    D:\move_script\thisbatchname

    which will execute the remaining command relative to the directory selected at the time of execution.

    There is a problem with the approach. Given that the xcopy could be fixed to perform the copy of the one file in the source subtree that matches the name in %%a, that search would need to be done 500 times - once for each entry in list.txt, which would be v.e.r.y. .s.l.o.w.

    So here's another approach:

    @ECHO OFF
    SETLOCAL
    rem The following settings for the directory and filename are names
    rem that I use for testing and deliberately includes spaces to make sure
    rem that the process works using such names. These will need to be changed to suit your situation.
    
    SET "sourcedir=u:\your files"
    SET "filename1=%sourcedir%\q78088112.txt"
    
    (
    FOR /f "delims=" %%e IN ('XCOPY /L /Y /S "%sourcedir%\*"') DO ECHO %%e^|%%~nxe
    )>"%temp%\####.exist"
    (
    FOR /f "usebackqdelims=" %%e IN ("%filename1%") DO ECHO ^|%%e
    )>"%temp%\####.incl"
    
    FOR /f "tokens=1delims=|" %%e IN ('findstr /e /L /g:"%temp%\####.incl" "%temp%\####.exist"') DO ECHO COPY "%%e" "destdirname"
    
    DEL "%temp%\####.excl" "%temp%\####.exist"
    GOTO :eof
    

    Note that if the filename does not contain separators like spaces, then both usebackq and the quotes around %filename1% can be omitted.

    The required COPY commands are merely ECHOed for testing purposes. After you've verified that the commands are correct, change ECHO COPY to COPY to actually copy the files. Append >nul to suppress report messages (eg. 1 file copied)

    First, perform an xcopy listing, creating a full filelist in a temporary file ####.exist with each line of the format fullfilename|filenameandextension

    Next, process the filename list to ####.incl, simply inserting a | before each filename

    Then find the first token of the lines in ####.exist using | as a delimiter (which becomes the full filename of the file to be copied) WHERE the line /e ends with any entry in the /g: file, ####.incl

    Note that | cannot appear in a legitimate filename.