Windows Command Line – Copy Files from Directory Tree to Folder

batchcommand linerobocopywindowsxcopy

I have a mirror of a large website that I need to reorganize, most of the images and files I've been able to programmatically move and relink up; however, there are a few (few is a relative term, we're talking 3,000 odd files) I need to locate within the mess of folders.

I know the filename(s) (I have big long lists and I'm assuming they're unique, or at least unique enough that I can fix any collision manually) but not their location within the file structure, and I need to copy them to a separate directory so that I can then upload them.

In short, I have a list like

file1.jpg
file2.doc
file4.ppt
filesomethingelse.this

in a file (say, filelist.txt).

And I have a folder structure like

folder\subfolder\file1.jpg
folder\subfolder\file2.doc
folder\subfolder2\filesomethingelse.this
folder\file3.jpg
folder\file4.ppt

and I want to get

secondFolder\file1.jpg 
secondFolder\file2.doc
secondFolder\file4.ppt 
secondFolder\filesomethingelse.this

Note that file3.jpg should not be copied because it is not on the list.

Something command line like (xcopy or robocopy) would be the best option I guess, so I can batch up the requests.

Hope this makes sense.

Best Answer

If you want to copy only those files whose names are listed in filelist.txt, and skip files that aren't (e.g., file3.jpg in your example), do

for /r folder %f in (*) do @findstr/i /x "%~nxf" filelist.txt > nul && copy %f secondfolder
  • %f is assigned the full pathname of each file under folder; %~nxf extracts the name and extension (i.e., the base filename; everything after the last \).
  • @ suppresses display of the following command.  This is cosmetic and discretionary.  Also, it is unnecessary if you put this command in a batch file and begin it with @echo off.
  • findstr looks for a string (or pattern) in a file (or other data set); it is essentially Windows' equivalent of grep.  We use it to determine whether each filename is in the filename list, filelist.txt.
    • /i — Do case insensitive matching.  You can leave this out if you're sure your list has correct capitalization.
    • /x — Match entire line (like grep -x).  This prevents filenames like le2.do from matching file2.doc.
  • > nul — equivalent to > /dev/null; this prevents the output from findstr from being displayed.  (Of course this is just to avoid cluttering the screen, and is optional.)
  • && — Do the next command (copy) if the previous command (findstr) succeeded.  (findstr succeeds if it finds a match; i.e., if the filename is in the list.)
  • If you have any filenames with funny characters in them, you may need to put the last %f into quotes ("%f") and maybe change the findstr command.
  • Before you run this command for real, you might want to change copy to echo copy, so you can do a dry run and see what the command will do.
  • If you put the command into a batch file, change all occurrences of % to %%.
  • If you want to get a listing (log) of where the files were found, you can do
for /r folder %f in (*) do @findstr/i /x "%~nxf" filelist.txt > nul && (echo %f & copy %f secondfolder)
Related Question