Reputation: 73
I am attempting to find all .PST files for the logged on user. However, I seem unable to add a path to 'Drive'. I would like to search all files under C:\users\ + $env:UserName
This command seems to find all PST files on C:\
$Res = Get-CimInstance CIM_DataFile -filter "Drive='c:' AND extension='pst'" -OutVariable m | Select-Object -Property Name
However when I change this to:
$Res = Get-CimInstance CIM_DataFile -filter "Drive='C:\users\' + $env:UserName AND extension='pst'" -OutVariable m | Select-Object -Property Name
or even just:
$Res = Get-CimInstance CIM_DataFile -filter "Drive='C:\users\' AND extension='pst'" -OutVariable m | Select-Object -Property Name
I get the following error:
Get-CimInstance : Invalid query At C:\Users\mntle2\Documents\PSTMig.ps1:2 char:8 + $Res = Get-CimInstance CIM_DataFile -filter "Drive='c:\users\' AND ex ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Get-CimInstance], CimException + FullyQualifiedErrorId : HRESULT 0x80041017,Microsoft.Management.Infrastructure.CimCmdlets.GetCimInstanceCommand
Can somebody please assist me in resolving this issue?
Upvotes: 2
Views: 1459
Reputation: 439682
tl;dr
In order to perform a CIM-based file search in a directory subtree (as opposed to a single directory), you must compare the Path
property with a drive-relative path wildcard expression using the LIKE
operator.
"Drive='C:' AND Extension='pst' AND Path LIKE '\\Users\\$env:USERNAME\\%'"
However this is INEFFICIENT AND SLOW, because this kind of operation still searches ALL files.
"Drive='C:' AND Extension='pst' AND Path='\\Users\\$env:USERNAME\\'"
\\
)Additionally, this functionality was temporarily broken in some versions of Windows 10 (observed on at least one build in the 1703
servicing channel).
Thus, in order to efficiently locate files anywhere in a directory's subtree, use Get-ChildItem
instead (with Invoke-Command -ComputerName
for remoting, if needed) - see below.
Get-ChildItem
:$res = (Get-ChildItem -Recurse $HOME -File -Filter *.pst -OutVariable m).FullName
Note: Strictly speaking Select-Object -Property Name
in your original command doesn't return the full file paths directly, the way the above command does, but wraps them in custom objects whose .Name
property contains them.
In order to run this command on remote machines, pass it to Invoke-Command -ComputerName
(from an elevated session, with PS remoting set up):
$res = Invoke-Command -ComputerName $targetComputer {
(Get-ChildItem -Recurse $HOME -File -Filter *.pst -OutVariable m).FullName
}
Here's the complete solution to the OP's problem, but, as stated:
it is inefficient and slow
it is broken on at least one Windows 10 build in the 1703
update channel.
$filter = "Drive='C:' AND Extension='pst' AND Path LIKE '\\Users\\$env:USERNAME\\%'"
$Res = Get-CimInstance CIM_DataFile -Filter $filter -OutVariable m |
Select-Object -Property Name
The -Filter
argument accepts an WQL expression, which can be tricky to construct:
Drive
can only accept a drive specification, so in order to search in specific directory you must use Path
to target a - drive-relative - directory path.
The Path
argument must have its \
chars. doubled (\\
), because \
acts as an escape character in string operands.
If you use operator =
to specify a path, only the specified directory itself is searched, which, however, is efficient; note that the path must then end in \\
.
By contrast, in order to search the specified path and its entire subtree :
LIKE
instead of =
and%
to the path; (in WQL (and SQL, which WQL is based on), %
is the equivalent of the usual *
wildcard character,and _
corresponds to ?
)Upvotes: 1
Reputation: 1212
You can try to use the path
property in your query instead:
$Res = Get-CimInstance CIM_DataFile -filter "Drive='C:' AND path='\\users\\' AND extension='pst'" -OutVariable m | Select-Object -Property Name
Upvotes: -1