Lazy Diary @ Hatena Blog

PowerShell / Java / miscellaneous things about software development, Tips & Gochas. CC BY-SA 4.0/Apache License 2.0

You should not pass the result of Get-ChildItem into Get-Content (and the like) directly

Context:

You can pass the result of Get-ChildItem into Get-Content directly:

PS /home/satob/tmp> Get-ChildItem | Where-Object { $_.Name -like "*.csv" } | ForEach-Object { Get-Content $_ }          
"a","x"
"b","2"
...

Problem:

You cannot pass the result of Get-ChildItem into Get-Content directly when you Get-ChildItem from other than current directory:

PS /home/satob> Get-ChildItem /tmp | Where-Object { $_.Name -like "*.csv" } | ForEach-Object { Get-Content $_ }         
Get-Content : Cannot find path '/home/satob/foobar.csv' because it does not exist.
At line:1 char:80
+ ... -Object { $_.Name -like "*.csv" } | ForEach-Object { Get-Content $_ }
+                                                          ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (/home/satob/foobar.csv:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand

It is troublesome because the problem will not occur when you test with the files in current directory.

Reason:

The result of Get-ChildItem is handled as relative path when you pass them to Get-Content.

Note: The problem will not occur even without FullName when you use wildcard with Get-ChildItem.

PS /home/satob> Get-ChildItem tmp/*.csv | ForEach-Object { Get-Content $_ }                                             
"a","x"
"b","2"
...

Solution:

You should specify FullName property explicitly:

PS /home/satob> Get-ChildItem tmp/ | Where-Object { $_.Name -like "*.csv" } | ForEach-Object { Get-Content $_.FullName }
"a","x"
"b","2"
...

You can also use FullName property with wildcards:

PS /home/satob> Get-ChildItem tmp/*.csv | ForEach-Object { Get-Content $_.FullName }                                    
"a","x"
"b","2"
...

Note: You should not use Name property with or without wildcards. It contains relative path:

PS /home/satob> Get-ChildItem tmp/ | Where-Object { $_.Name -like "*.csv" } | ForEach-Object { Get-Content $_.Name }    
Get-Content : Cannot find path '/home/satob/a.csv' because it does not exist.
At line:1 char:80
+ ... ct { $_.Name -like "*.csv" } | ForEach-Object { Get-Content $_.Name }
+                                                     ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (/home/satob/a.csv:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
PS /home/satob> Get-ChildItem tmp/*.csv | ForEach-Object { Get-Content $_.Name }                                        
Get-Content : Cannot find path '/home/satob/a.csv' because it does not exist.
At line:1 char:44
+ Get-ChildItem tmp/*.csv | ForEach-Object { Get-Content $_.Name }
+                                            ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (/home/satob/a.csv:String) [Get-Content], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand