Home > front end >  Powershell Get Files from Directory and search for them in another Directory
Powershell Get Files from Directory and search for them in another Directory

Time:12-23

Dear wise Stackoverflow Community

Is it possible with powershell, to get all filenames in a directory and search for them each in another directory?

Something like:

Path A (C:\Temp):

C:\Temp\Test2\Test.docx
C:\Temp\Test\test.txt
C:\Temp\Test\file.html`

and search for each file (Test.docx,test.txt,file.html) in a different path e.g. C:\Filesnew ?

and in the best case, the export to csv would be something like:

| Filename  | Filepath                 | Found? | FoundIn                                 |
| --------  | ------------------------ |--------| ----------------------------------------|
| Test.docx | C:\Temp\Test2\Test.docx  | y      | C:\Filesnew\TransferedFiles\Test.docx   |
| test.txt  | C:\Temp\Test\test.txt    | n      |                                         |
| file.html | C:\Temp\Test\file.html   | y      | C:\Filesnew\webfiles\file.html          |

I'm currently stuck at this code:

$files = gci -r *   | select-object name, fullname
foreach ($file in $files)
{
  gci -path C:\Filesnew -recurse | where {$_.Name -match $file.Name} | select-object $files.Name $files.fullname, $file.fullname | Export-CSV C:\test.csv  
}     

Can you help me out?

CodePudding user response:

This requires a bit of logic, ideally the more efficient way to go about this is to have a hashtable with all File Names and their corresponding Absolute Paths excluding the target directory (C:\Filesnew) for fast lookups.

$targetDir = 'C:\Filesnew'

$queue = [Collections.Generic.Queue[IO.DirectoryInfo]]::new()
$queue.Enqueue((Get-Item C:\))

# This logic below builds a map having:
#  - Keys as the FileName
#  - Values as the corresponding Absolute Paths for each FileName
$map = @{}
while($queue.Count) {
    try {
        $target = $queue.Dequeue()
        foreach($item in $target.EnumerateFileSystemInfos()) {
            if($item.FullName.StartsWith($targetDir, $true, $null)) {
                # exclude the `$targetDir` and any directory or file in it
                continue
            }

            if($item -is [IO.DirectoryInfo]) {
                $queue.Enqueue($item)
                continue
            }

            if(-not $map.ContainsKey($item.Name)) {
                $map[$item.Name] = [Collections.Generic.List[string]]::new()
            }

            $map[$item.Name].Add($item.FullName)
        }
    }
    catch {
        # you can add error handling here but most errors will be Access Denied
        # can also leave blank here to ignore errors
    }
}

# now that we have our map of FileNames and Absolute Paths
# query the target Directory
Get-ChildItem $targetDir -Recurse -File | ForEach-Object {
    # construct the desired output
    [pscustomobject]@{
        FileName = $_.Name
        FilePath = $_.Fullname
        Found    = ('n', 'y')[$map.ContainsKey($_.Name)]
        FoundIn  = $map[$_.Name] -join ', '
    }
# Export the output to CSV
} | Export-Csv C:\test.csv -NoTypeInformation
  • Related