Home > Net >  Trying to return filetype for all users appdata using PowerShell
Trying to return filetype for all users appdata using PowerShell

Time:07-14

I am struggling with a PowerShell script to return .json file types in all users %APPDATA% folders. When I run it in ISE, it returns "Get-ChildItem : Access is denied" and when I run ISE as admin, no output is returned.

Here is the script I am working with:

Get-ChildItem C:\Users\*\AppData\Roaming -Filter '*.json' -File -Recurse -Force -ErrorAction SilentlyContinue |
ForEach-Object {
    Write-Host $('.json found in {1}' -f $_.Name, ([System.IO.Path]::GetDirectoryName($_.FullName)))
    }

Any help would be greatly appreciated!

CodePudding user response:

tl;dr

  • It is the use of the -File switch that prevents your command from working - see next section.

  • Given that you're filtering by *.json and that directories are unlikely to match that pattern, you can simply omit it.

    • If you do need to guard against that, insert a Where-Object { -not $_.PSIsContainer } pipeline segment after the Get-ChildItem call; in PowerShell (Core) 7 , you can simplify to
      Where-Object -Not PSIsContainer
# Do NOT use -File
# Note: Run from an ELEVATED session (as admin), which is necessary to
#       access other users' directories.
Get-ChildItem C:\Users\*\AppData\Roaming -Filter '*.json' -Recurse -Force -ErrorAction SilentlyContinue |
  ForEach-Object { '{0} found in {1}' -f $_.Name, $_.DirectoryName }

The reason that Get-ChildItem's -File doesn't work in your case is that you're combining it with a -Path value that is an actual wildcard expression rather than a literal path:

  • The wildcard expression is resolved first and - perhaps surprisingly - if directories are among the matching paths, they are returned as themselves, rather than listing their children (what is inside them); the latter only happens with literal input paths.

  • In your case, only directories match and the -File switch is therefore applied to them, not to their children. Since directories don't match the -File switch (by definition aren't files), there is no output.

    • Whether or not the -Recurse switch is also present then makes no difference, given that there's nothing to recurse into.

As an aside:

If you wanted to make your command work without -Recurse, -File can be made to work, but only if you append \* to your input wildcard (the positionally implied -Path argument), so as to force enumeration of the children to match the -File and the -Filter against:

# Without recursion and a trailing /*, -File works
Get-ChildItem C:\Users\*\AppData\Roaming\* -File -Filter '*.json'

However, since PowerShell then needs to enumerate all children first, it is then simpler and more efficient to omit -Filter and append its pattern directly to the input wildcard:

# No -Filter, pattern appended to input path
Get-ChildItem C:\Users\*\AppData\Roaming\*.json -File
  • Related