Maxime
Maxime

Reputation: 858

The given path's format is not supported (listing files)

I'm trying to move all files from a NAS to a cloud provider, which does not allow the char ?<>|/\\*:" in its filenames, unfortunately some of the files do have these char in their filenames.

So I would like to fix these filenames before doing the migration, and thus I had the idea to list the forbiden filenames, but the forbiden char crash the Get-childItem command and I'm a bit stuck

Here's the command I use

 Get-ChildItem $myPath -Recurse -Force -File | Where-Object {$_.name -match '[?<>|/\\*:"]+'} | select fullname, name

And here's the output I get :

Get-ChildItem : The given path's format is not supported
Char, Line:1 : 1
+ Get-ChildItem path -Recurse -Force  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-ChildItem], NotSupportedException
    + FullyQualifiedErrorId : System.NotSupportedException,Microsoft.PowerShell.Commands.GetChildItemCommand

Is there a way to make the command fail but still tell me where was the file which crashed it ? Or is there another command or parameter to use to do what I want ?

Edit : For now I found a workaround, rather than mounting the distant nas with New-PSDrive, I sshed into the NAS and used the linux bash which was installed on it and supports these filenames but I am still interested by the answer to how to do it with powershell

Upvotes: 1

Views: 495

Answers (1)

mklement0
mklement0

Reputation: 439767

Use the the common -ErrorVariable (-ev) parameter parameter in combination with the common -ErrorAction (-ea) parameter:

Get-ChildItem $myPath -Recurse -Force -File -ea SilentlyContinue -ev errs | 
  Where-Object {$_.name -match '[?<>|/\\*:"]+'} | select fullname, name

Write-Verbose -vb 'The following paths caused errors:'
$errs.TargetObject
  • -ea SilentlyContinue silences error display (and continues execution as long as the errors are non-terminating, which they typically are).

  • -ev errs captures the non-terminating errors in self-chosen variable $errs, which can be inspected later.

The .TargetObject property of the System.Management.Automation.ErrorRecord instances collected in $errs contains the source object that triggered the error, which in the case at hand is the full path of the file-system object; $errs.TargetObject lists them all, across all error objects in the collection, courtesy of member-access enumeration.


Update:

  • The above doesn't seem to help in the specific case at hand, as seemingly only a single error record is returned that doesn't have .TargetObject filled in and mentions only the starting directory of the recursive enumeration.

  • The Include * approach shown below helped to at least narrow the problem down to individual directories containing offending files.

Adding -Include * to force explicit processing of individual files in each directory may help:

# Tries to find offending file names only, via `$errs`
$null = Get-ChildItem $myPath -Recurse -Force -File -Include * -ea SilentlyContinue -ev errs

Another option, given that you say that passing -Directory doesn't report errors, is to apply Get-Item * -Force to each directory and see if the offending file names can at least be narrowed down to specific directories:

# Tries to find offending file names only, via `$errs`
$null = & { Get-Item $myPath; Get-ChildItem $myPath -Recurse -Force -Directory } |
  Get-Item -Path { Join-Path $_.FullName * } -Force -ea SilentlyContinue -ev errs

Upvotes: 2

Related Questions