vonN00B
vonN00B

Reputation: 13

Batch script to copy files listed in text file from a folder and its subfolders to a new location

I would like a batch file to copy all of the files listed in a text file from one destination to another. The source destination may have multiple subfolders and I would like the batch to search each subfolder for the file name.

I do not want copy the folders themselves, only the files.

I have the following code but it isn't recognizing the (%file_list%)

set src=c:\files\sourcefolder\
set dst=c:\files\destinationfolder\
set file_list=c:\\files\files.txt

for /r "%src%" %%i in (%file_list%) do copy "%%i" "%dst%" >notcopied.txt

I also want the file to write a text file called 'notcopied.txt' so I can see if any required files were not in the source folder. I want that file written to the destination folder.

For example:

files.txt contains
File1.pdf
File2.pdf
File3.pdf

source folder contains

File1.pdf
File2.pdf

notcopied.txt will then show

File3.pdf

Thanks for any insight.

Upvotes: 1

Views: 8800

Answers (1)

spirit
spirit

Reputation: 3415

First, you need to enable extended command line

SETLOCAL ENABLEEXTENSIONS

so you can use the extended FOR loop. Second, you need to enable delayed expansion of environment variables

SETLOCAL ENABLEDELAYEDEXPANSION

so you can check if searched file was found later.

Here is the result:

@echo off
SETLOCAL ENABLEEXTENSIONS
SETLOCAL ENABLEDELAYEDEXPANSION

SET src=.\sourcefolder\
SET dst=.\destinationfolder\
SET file_list=.\files.txt

FOR /F %%f IN (%file_list%) DO (
    SET found=false
    FOR /F "usebackq" %%s IN (`where /R %src% %%f`) DO (
        SET found=true
        echo "%%s => %dst%\%%f"
        @copy /y "%%s" "%dst%\%%f" 
    )
    IF "!found!" == "false" (
        echo %%f is not found!
    )
)

ENABLEDELAYEDEXPANSION is needed here for variable %found%, without it %found% will always be false. Furthermore, to expand environment at runtime you must use !found! syntax.

You can call it like

batch.bat > result.log

and the results will be writen to file result.log


UPDATE: here is a version of bacth without variable found and with suggestions from @aschipfl:

@echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

SET "src=.\sourcefolder\"
SET "dst=.\destinationfolder\"
SET "file_list=.\files.txt"

FOR /F "usebackq eol=| delims=" %%f IN ("%file_list%") DO (
    rem just searching to find out existense of file
    WHERE /Q /R "%src%" "%%f"
    IF "!ERRORLEVEL!" == "0" (
        FOR /F "usebackq eol=| delims=" %%s IN (`WHERE /R "%src%" "%%f" 2^> nul`) DO (
            echo "%%s => %dst%\%%f"
            @copy /y "%%s" "%dst%\%%f" 
        )
    ) ELSE (
        echo %%f is not found!
    )
)

This version can handle files with a space symbol in the filename.
But both of the solutions have same restriction: sourcefolder can't contain any spaces in the name. For some reason command WHERE /R "%src%" "%%f" doesn't working, while WHERE /R %src% "%%f" working just as expected.


UPDATE2: here is the version, that produces result.log:

@echo off
SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION

SET "src=.\sourcefolder\"
SET "dst=.\destinationfolder\"
SET "file_list=.\files.txt"
SET "out=.\result.log"
echo > %out%

FOR /F "usebackq eol=| delims=" %%f IN ("%file_list%") DO (
    rem just searching to find out existense of file
    WHERE /Q /R %src% "%%f"
    IF "!ERRORLEVEL!" == "0" (
        FOR /F "usebackq eol=| delims=" %%s IN (`WHERE /R %src% "%%f"`) DO (
            echo "%%s => %dst%\%%f" >> %out%
            @copy /y "%%s" "%dst%\%%f" 
        )
    ) ELSE (
        echo %%f is not found! >> %out%
    )
)

Upvotes: 2

Related Questions