4

I have a directory with thousands of files named as number.jpg (ex: 100152.jpg, 100153.jpg). I don't want to copy everything in this directory — only the files with the exact name as the names in a text file list that I have created.

There are about 36k names in this shorter list — I want to copy all the files in the large directory that have the same names as the ones in the list into a separate folder.

How would I be able to do this without going one by one on a Windows system?

1
4

You can use a FOR /F and reference the full path of the file list as show below.

This will essentially read each line of the file list you point to, line by line, and iterate the returned value (content of each line) to the XCOPY command to process accordingly.

Command Line Syntax

FOR /F "USEBACKQ TOKENS=*" %F IN ("C:\Folder\FileList.txt") DO XCOPY /F /Y "C:\SourceFolder\%~F" "C:\DestinationFolder\"

Batch Script Syntax

@ECHO ON

SET FileList=C:\Folder\FileList.txt
SET Source=C:\SourceFolder
SET Destination=C:\DestinationFolder

FOR /F "USEBACKQ TOKENS=*" %%F IN ("%FileList%") DO XCOPY /F /Y "%Source%\%%~F" "%Destination%\"

GOTO :EOF

Script Logic Notes

  • The USEBACKQ option used in the FOR loop will ensure the file list can still be read if the file list name or it's path has any spaces in it and you need to double quote the file list path

    • E.g. SET FileList=C:\Folder Name\File List.txt
      • Without the USEBACKQ the FOR loop would error out in a case like this
  • The TOKENS=* option used in the FOR loop will ensure the the entire value is returned as it's read from the file list even if that value has a space in it

    • E.g. File list has a value of File 00 11.jpg so the value has a space on a line

      • Without the TOKENS=* the FOR loop would only return the value portion of that line before the first space and not the value as expected (i.e. File)

Using these options even when not needed does not seem to cause any harm and should you ever introduce such a value or variable into the mix of the script, it'd already be able to handle such cases accordingly.


Further Resources

3
  • How one does this with PowerShell? – churchill Apr 8 '20 at 0:40
  • 1
    @churchill You have to set a variable with Get-Content c:\file.txt to the file or something like that, and then loop over each line in that file as an array. There should be all sorts of answer around with more specific examples. Just look at the posts from here to see some superuser.com/search?q=get-content. Consider opening a question once you dig and if you have trouble with anything. – Pillsbury IT Doughboy Apr 8 '20 at 0:49
  • Thank you, I just posted the question as I'm having some problems with PS that I don't understand. – churchill Apr 8 '20 at 1:44
3

I'd use bash anytime.

cat list.txt | xargs -I {} cp {} <destination folder>

Or, since I've come to prefer parallel over xargs:

cat list.txt | parallel cp {} <destination folder>

On Windows, I'd go with cygwin, but you might consider cmder, Git-for-Windows, WSL and more...


But you can do it almost as easily in Powershell:

cat list.txt  | ForEach {cp $_ <destination folder>}

Apparently, Microsoft wants a certain category of users to feel at ease using Powershell, because it recognizes several well-known commands from the UNIX world. These are but aliases to the equivalent cmdlets and a list can be found by invoking Get-Alias (or simply alias if you prefer):

cat -> Get-Content
clear -> Clear-Host
cp -> Copy-Item
curl -> Invoke-WebRequest
diff -> Compare-Object
echo -> Write-Output
history -> Get-History
kill -> Stop-Process
ls -> Get-ChildItem
man -> help
mount -> New-PSDrive
mv -> Move-Item
pwd -> Get-Location
rm -> Remove-Item
sleep -> Start-Sleep
wget -> Invoke-WebRequest
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.