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?
12 Answers
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 :EOFScript Logic Notes
The
USEBACKQoption 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
USEBACKQthe FOR loop would error out in a case like thisThe
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.jpgso 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
3I'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