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