要测试文件是否可读,您可以尝试打开它。如果出现错误,则该文件不可读。您需要根据需要捕获或捕获异常或因错误而停止。请记住,Windows 会锁定打开以进行写入的文件,因此应用程序需要预料到它们有时无法打开文件。
如果确实有必要,您可以使用类似的方法来测试是否可以读取文件:
try {
[System.IO.File]::OpenRead($FullPathName).Close()
$Readable = $true
}
catch {
$Readable = $false
}
这是为了测试您是否可以写入文件:
try {
[System.IO.File]::OpenWrite($FullPathName).Close()
$Writable = $true
}
catch {
$Writable = $false
}
如果您确实需要的话,该逻辑很容易包装到函数中。
就文件类型而言,Windows 文件系统中的几乎所有内容都是普通文件或目录,因为 Windows 没有“一切都是文件”约定。所以,通常你可以按如下方式进行测试:
# Test if file-like
Test-Path -Path $Path -Leaf
# Test if directory-like
Test-Path -Path $Path -Container
如果您正在与FileInfo
or DirectoryInfo
对象(即,输出Get-Item
, Get-ChildItem
,或代表文件或目录的类似对象)您将拥有PSIsContainer
属性将告诉您该项目是文件还是目录。
这可能涵盖了 99.999% 的情况。
但是,如果您需要知道某个文件是否是到文件的 NTFS 硬链接(罕见,但最古老),NTFS 到目录的连接 https://en.wikipedia.org/wiki/NTFS_junction_point, an NTFS符号链接 https://en.wikipedia.org/wiki/NTFS_symbolic_link, an NTFS卷安装点 https://en.wikipedia.org/wiki/NTFS_volume_mount_point, or 任何类型的 NTFS 重分析点 https://en.wikipedia.org/wiki/NTFS_reparse_point,事情变得更加复杂。 [这个答案 https://stackoverflow.com/a/48586946/696808很好地描述了前三个。]
让我们创建一个简单的 NTFS 文件夹来测试:
# Create a test directory and change to it.
New-Item -Path C:\linktest -ItemType Directory | Select-Object -ExpandProperty FullName | Push-Location
# Create an empty file
New-Item -Path .\file1 -ItemType file -Value $null | Out-Null
New-Item -Path .\file2 -ItemType file -Value $null | Out-Null
# Create a directory
New-Item -Path .\dir1 -ItemType Directory | Out-Null
# Create a symlink to the file
New-Item -ItemType SymbolicLink -Path .\sfile1 -Value .\file1 | Out-Null
# Create a symlink to the folder
New-Item -ItemType SymbolicLink -Path .\sdir1 -Value .\dir1 | Out-Null
# Create a hard link to the file
New-Item -ItemType HardLink -Path .\hfile1 -Value .\file1 | Out-Null
# Create a junction to the folder
New-Item -ItemType Junction -Path .\jdir1 -Value .\dir1 | Out-Null
# View the item properties
Get-ChildItem -Path . | Sort-Object Name | Format-Table -Property Name, PSIsContainer, LinkType, Target, Attributes -AutoSize
你的输出将是:
Name PSIsContainer LinkType Target Attributes
---- ------------- -------- ------ ----------
dir1 True {} Directory
file1 False HardLink {C:\linktest\hfile1} Archive
file2 False {} Archive
hfile1 False HardLink {C:\linktest\file1} Archive
jdir1 True Junction {C:\linktest\dir1} Directory, ReparsePoint
sdir1 True SymbolicLink {C:\linktest\dir1} Directory, ReparsePoint
sfile1 False SymbolicLink {C:\linktest\file1} Archive, ReparsePoint
请注意,两者file1
and hfile1
是硬链接,尽管file1
并不是这样创建的。
要清理上述垃圾,请执行以下操作:
Get-ChildItem -Path C:\linktest\ | ForEach-Object { $_.Delete() }
There's 中的一个错误Remove-Item https://github.com/powershell/powershell/issues/621删除一些容器链接,这会阻止命令删除项目。
一般的解决方案是获取该项目并对其进行测试:
# Get the item. Don't use Get-ChildItem because that will get a directory's contents
$Item = Get-Item -Path $Path
# Is it a container
$Item.PSIsContainer
# Is it a link of some kind?
[System.String]::IsNullOrWhiteSpace($Item.LinkType)
$Item.LinkType -eq 'Junction'
# Is it a Reparse Point?
($Item.Attributes -band [System.IO.FileAttributes]::ReparsePoint) -eq [System.IO.FileAttributes]::ReparsePoint
还有其他几个潜在的属性:
PS> [System.Enum]::GetNames([System.IO.FileAttributes])
ReadOnly
Hidden
System
Directory
Archive
Device
Normal
Temporary
SparseFile
ReparsePoint
Compressed
Offline
NotContentIndexed
Encrypted
IntegrityStream
NoScrubData
注意Device被记录为保留供将来使用 https://msdn.microsoft.com/en-us/library/system.io.fileattributes(v=vs.110).aspx。 Windows 中没有设备文件类型。
对于卷安装点,我不能 100% 确定它们的外观。我知道您可以在 Windows 8.1 及更高版本上创建它们Get-Partition
随后是适当的Add-PartitionAccessPath
,但我目前使用的是 Windows 7。恐怕我现在没有办法对此进行测试。
最后,我不知道 Linux 上的 PowerShell Core 6.0 到底如何处理文件类型。