OK, here’s a task that’s supposedly very easy, but can get you raging due to the oddities of PowerShell formatting. How do we list all directories that have a particular set of files available? For the sake of simplicity, let’s just examine the case of two files and call them File1.txt and File2.txt. Remember, we need all directories that contain BOTH of these files.
You can browse a gazillion examples online, all using different variations of the -Filter or -Include parameter of the Get-ChildItem cmdlet. Something like this for example:
dir C:\ -Include File1.txt, File2.txt -Recurse
which is equivalent to:
dir C:\ -Recurse| ? {$_.Name -eq "File1.txt" -or $.Name -eq "File2.txt" }
Note the damned -OR operator however. This returns ANY directory that has ANY of the files we are interested in, not only the directories that have BOTH of them. And since the comparison is done against each individual file, there’s no point in replacing the -OR with -AND operator.
On the other hand, the output already contains the information we are interested in – among the list of all directories that include any of the file names, there are some that include ALL of them. So the question is how to filter only those entries?
After banging my head against the keyboard for a while, this is the solution I came up with – use the Group-Object cmdlet and then use another filter to get the entries we need (in this case check whether the count of values is exactly 2):
dir C:\ -Include File1.txt, File2.txt -Recurse | Group Directory | ? {$_.Count -eq 2}
That’s the list of all directories that have both files we are querying for. As the format is again not very useful, you can get the Values (which returns the full System.IO.DirectoryInfo object) and for example sort by the Last Modified Date to get the newest/oldest directory:
(dir C:\ -Include File1.txt, File2.txt -Recurse | Group Directory | ? {$_.Count -eq 2}).Values | sort LastWriteTime -Descending | select -First 1 | select -ExpandProperty FullName
Man, that was exhausting exercise. Hope it helps someone 🙂
Do let me know if there’s an easier way to do this!
@Stefan – “dir” is an alias for Get-ChildItem, when executed in a PowerShell window…
Way to complicated. Dir is not Powershell – its DOS. Use Get-ChildItem.
Get-ChildItem -path C: -Recurse | where-object {($_.Name -like “File1.txt”) -and ($_.Name -like “File2.txt”)}
Yeah, try it? 🙂
Your example matches the filenames one at a time, and you cannot have a file named both File1.txt AND File2.txt. You need to run the operation against the full list of files in the directory, and using the -Include parameter is pretty much the only easy way to do so. Thus the need for OR operator, and the need to actually check the number of results is 2.