How to get Get-ChildItem to handle path with non-breaking space How to get Get-ChildItem to handle path with non-breaking space powershell powershell

How to get Get-ChildItem to handle path with non-breaking space


It's still unclear why Sandra's code didn't work: PowerShell v2+ is capable of retrieving files with paths containing non-ASCII characters; perhaps a non-NTFS filesystem with different character encoding was involved?

However, the following workaround turned out to be effective:

$objFile = Get-ChildItem -Path ($inFile -replace ([char] 0xa0), '?')
  • The idea is to replace the non-breaking space char. (Unicode U+00A0; hex. 0xa) in the input file path with wildcard character ?, which represents any single char.

  • For Get-ChildItem to perform wildcard matching, -Path rather than -LiteralPath must be used (note that -Path is actually the default if you pass a path argument positionally, as the first argument).

  • Hypothetically, the wildcard-based paths could match multiple files; if that were the case, the individual matches would have to be examined to identify the specific match that has a non-breaking space in the position of the ?.


Get-ChildItem is for listing children so you would be giving it a directory, but it seems you are giving it a file, so when it says it cannot find the path, it's because it can't find a directory with that name.

Instead, you would want to use Get-Item -LiteralPath to get each individual item (this would be the same items you would get if you ran Get-ChildItem on its parent.

I think swapping in Get-Item would make your code work as is.

After testing, I think the above is in fact false, so sorry for that, but I will leave the below in case it's helpful, even though it may not solve your immediate problem.


But let's take a look at how it can be simplified with the pipeline.

First, you're starting with an empty array, then calling a command (Get-Content) which likely already returns an array, wrapping that in an array, then concatenating it to the empty one.

You could just do:

$inFiles = Get-Content -Path "C:\Users\sw_admin\FoundLinks.csv"

Yes, there is a chance that $inFiles will contain only a single item and not an array at all.

But the nice thing is that foreach won't mind one bit!

You can do something like this and it just works:

foreach ($string in "a literal single string") {    Write-Host $string}

But Get-Item (and Get-ChildItem for that matter) accept pipeline input, so they accept multiple items.

That means you could do this:

$inFiles = Get-Content -Path "C:\Users\sw_admin\FoundLinks.csv" | Get-Itemforeach ($inFile in $inFiles) {    Write-Host("Processing: " + $inFile)    New-Object PSObject -Prop @{         FullName = $inFile.FullName        ModifyTime = $inFile.LastWriteTime    }} 

But even more than that, there is a pipeline-aware cmdlet for processing items, called ForEach-Object, to which you pass a [ScriptBlock], in which $_ represents the current item, so we could do it like this:

Get-Content -Path "C:\Users\sw_admin\FoundLinks.csv" |     Get-Item |    ForEach-Object -Process {        Write-Host("Processing: " + $_)        New-Object PSObject -Prop @{             FullName = $_.FullName            ModifyTime = $_.LastWriteTime        }    }

All in one pipeline!

But further, you're creating a new object with the 2 properties you want.

PowerShell has a nifty cmdlet called Select-Object which takes an input object and returns a new object containing only the properties you want; this would make for a cleaner syntax:

Get-Content -Path "C:\Users\sw_admin\FoundLinks.csv" |     Get-Item |    Select-Object -Property FullName,LastWriteTime

This is the power of the the pipeline passing real objects from one command to another.

I realize this last example does not write the processing message to the screen, however you could re-add that in if you wanted:

Get-Content -Path "C:\Users\sw_admin\FoundLinks.csv" |     Get-Item |    ForEach-Object -Process {        Write-Host("Processing: " + $_)        $_ | Select-Object -Property FullName,LastWriteTime    }

But you might also consider that many cmdlets support verbose output and try to just add -Verbose to some of your existing cmdlets. Sadly, it won't really help in this case.

One final note, when you pass items to the filesystem cmdlets via pipeline, the parameter they bind to is in fact -LiteralPath, not -Path, so your special characters are still safe.