search and copy files from a directory structure by reading a text file

1

I have a folder with many subfolders and files in them. I have a text file with the names of the files that I want copied to a separate destination folder. The filenames in the text file do not have path information.

In the destination folder, I want the file and its folder structure recreated. Is there a quick script for that? or a tool? I'm on Windows.

Regmi

Posted 2018-06-28T05:37:48.530

Reputation: 725

1

Starting point for you to build on but this is trivial for a batch scripter like myself.... FOR /F "USEBACKQ TOKENS=*" %A IN ("C:\Folder\Path\TextFile.txt") DO ECHO %~A. . . https://ss64.com/nt/for_cmd.html . . . Read over some of my answer that may be applicable just pick some and read as I'm sure I've helped with this before for someone: https://superuser.com/search?q=user%3A510662+body%3A+for+%2Ff

– Pimp Juice IT – 2018-06-28T05:48:58.330

Answers

2

The following PowerShell script should do what you want.

Change the first three variables to fit your environment.

## Q:\Test\2018\06\28\SU_1334840.ps1
#Requires -Version 3

# get files to copy from file in same foler
$FileList = Get-Content '.\FileList.txt'
$BaseSrc = 'X:\Source\path\'
$BaseDst = 'Y:\Destination\path\'

ForEach ($File in $FileList){
   ForEach ($Find in (Get-ChildItem $BaseSrc$File -File -Recurse)) {
       $DestFile = Join-Path $BaseDst ($Find.FullName.Replace($BaseSrc,'') )
       $DestDir = Split-Path $DestFile
       If (!(Test-Path $DestDir)){ MD $DestDir |Out-Null}
       # "Copying {0} to {1}" -f $Find.FullName,$DestFile
       Copy-Item $Find.FullName $DestFile
    }
}

To see what's going on while the script works, remove the # before "Copying...

The script requires at least PowerShell version 3

Depending on the size of your list / the number of files and subdirs in your source tree, this a bit different approach may be faster.

## Q:\Test\2018\06\28\SU_1334840_2.ps1
#Requires -Version 3

# get files to copy from file in same foler
$FileList = Get-Content '.\FileList.txt'
$BaseSrc = 'X:\Source\path\'
$BaseDst = 'Y:\Destination\path\'

ForEach ($File in (Get-ChildItem $BaseSrc -File -Recurse)) {
    If ($File.Name -in $FileList) {
       $DestFile = Join-Path $BaseDst ($File.FullName.Replace($BaseSrc,'') )
       $DestDir = Split-Path $DestFile
       If (!(Test-Path $DestDir)){ MD $DestDir |Out-Null}
       "Copying {0} to {1}" -f $File.FullName,$DestFile
       Copy-Item $File.FullName $DestFile
    }
}

Sample output:

> . Q:\Test\2018\06\28\SU_1334840.ps1
Copying C:\sys\7z.dll to A:\Test\sys\7z.dll
Copying C:\sys\7z.exe to A:\Test\sys\7z.exe
Copying C:\sys\ClipBoard.exe to A:\Test\sys\ClipBoard.exe
Copying C:\sys\ClipBoard.txt to A:\Test\sys\ClipBoard.txt
Copying C:\sys\DUMPHEX.EXE to A:\Test\sys\DUMPHEX.EXE

LotPings

Posted 2018-06-28T05:37:48.530

Reputation: 6 150

this works, for some reason the script doesn't find some files like " 00-00-00_0001 0894 0007861.JPG". Is there way to list which files were not found? (Do you notice the space between opening inverted commas and the first 0 in that file name?! – Regmi – 2018-06-28T18:21:17.527

We found a solution for such files. We prepended all filesnames in the text file with a *. Thank you! – Regmi – 2018-06-28T19:05:55.347

Thanks for feedback, just out of interrest - which variant was faster in your tries? – LotPings – 2018-06-28T19:09:22.833

The first one was better in fact and I ended up using it! I have about 17k filenames in the FileList.txt and machine is a 16G RAM, Win 2012 Server. – Regmi – 2018-06-28T20:04:27.017

Wow, from that numbers I would have expected the latter one leading, but file server caching seems to turn it. – LotPings – 2018-06-28T20:11:12.353

You're right! My apologies. We'd tried with a sample file much smaller earlier. Indeed the second script is much faster than the first. :) Thanks again. [There was a problem though. We'd pre-pended * in all filenames. The second script doesn't like those stars, it doesn't produce any output. So we reverted the files list.] – Regmi – 2018-06-28T20:39:13.563