如果我写这样的东西......
$files = Get-ChildItem c:\my_files | sort LastAccessTime
foreach($file in $files)
{
Write-host "file is <$file>"
}
我得到了一个文件名列表。(仅文件名,不包含路径)
但如果我做一个小小的改动来排除一些以数字结尾的日志文件......
$files = Get-ChildItem c:\my_files -Exclude *[0-9].log | sort LastAccessTime
foreach($file in $files)
{
Write-host "file is <$file>"
}
然后我得到完整路径和文件名的列表。
为什么?
我可以理解选定的文件会改变,但是为什么输出的格式会改变呢?
更新 - 这是 powershell 版本 5.1.19041.3693,这引出了一个问题,为什么 windows 告诉我我已“更新”,为什么 powershell 没有与我所有的其他更新一起默认升级?
答案1
你所看到的是——不幸的——情境变化的字符串化的System.IO.FileInfo
和System.IO.DirectoryInfo
实例输出Get-ChildItem
在Windows PowerShell。
- 这问题已修复PowerShell(核心)7+- 后者现在始终如一通过以下方式对这些类型的实例进行字符串化完整路径(
.FullName
适当的价值)。
$file
通过在上下文中引用"..."
,即可扩展(插值)字符串,调用对象的.ToString()
方法来获取其字符串表示形式,这就是有问题的行为表现的地方:
根据
Get-ChildItem
调用的具体参数,输出对象按其文件/目录进行字符串化仅限名称或通过他们的完整路径。有关在什么特定情况下发生仅名称与完整路径字符串化的详细信息,请参阅这篇文章。
这解决方法是明确访问对象的相关属性:
- 使用
.FullName
获取完整路径。 .Name
如果您只需要文件/目录,请使用姓名。
请注意,为了嵌入表达比如一个属性访问"..."
,你需要将它$(...)
括在子表达式运算符:
为了在代码的精简重构环境中进行演示(使用ForEach-Object
处理每个对象,反映在自动$_
变量, 也隐性输出):
# By using .FullName (or .Name) it doesn't matter whether an
# -Exclude argument is present or not.
Get-ChildItem -File c:\my_files |
Sort-Object LastAccessTime |
ForEach-Object {
# If you only want the *names*, use $_.Name
"file is $($_.FullName)"
}
答案2
尝试以下两个实验:
Get-ChildItem c:\my_files | sort LastAccessTime | gm
和
Get-ChildItem c:\my_files -Exclude *[0-9].log | sort LastAccessTime | gm
仔细查看输出。列出的属性并不完全相同,并且似乎与输出格式的差异相关。
当要求 PS 打印不可打印的对象时,它会搜索默认方法使其可打印。在这种情况下,属性列表的差异似乎导致 PS 找到另一种方法来使目录对象可打印。
完整的答案需要解释为什么属性列表不同。但我希望这能对情况有所启发。