在powershell中检查文件是否可读且规则
我是powershell的新手,我想检查文件是否可读和正常。在unix中,我们可以使用-f&-r在一行中完成。例如,下面的shell脚本函数接受filename作为参数,并检查文件的可读性和规则性,powershell的等效功能是什么在powershell中检查文件是否可读且规则,shell,powershell,powershell-3.0,powershell-4.0,Shell,Powershell,Powershell 3.0,Powershell 4.0,我是powershell的新手,我想检查文件是否可读和正常。在unix中,我们可以使用-f&-r在一行中完成。例如,下面的shell脚本函数接受filename作为参数,并检查文件的可读性和规则性,powershell的等效功能是什么 _ChkRegularFile_R() # checks whether a file is regular and readable { _CRFRfilename=$1 # name of th
_ChkRegularFile_R() # checks whether a file is regular and readable
{
_CRFRfilename=$1 # name of the file to be checked
_CRFRsts=1 # default is error
if [ -f "$_CRFRfilename" ]
then
if [ -r "$_CRFRfilename" ]
then
_CRFRsts=0 # success: regular file is readable
fi
fi
return $_CRFRsts
}
哦
这不是我经常做的事,但如果记忆有用的话。在*nix中,包含数据的常规文件是目录,再说一次,在普通的豪华服装下,我不必担心什么 那么您正在测试对象是可写文件(和/或非零)还是目录或二进制文件 所以,在时尚中,在v3之前。。。你这样做
$IsDir = {$_.PsIsContainer}
$IsFile = {!$_.PsIsContainer}
ls D:\Temp | Where $IsDir
lsectory: D:\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 1/4/2018 2:31 PM ArchiveDestination
d----- 1/4/2018 1:40 PM ArchiveSource
d----- 1/1/2018 3:34 PM diff
...
ls D:\Temp | Where $IsFile
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/7/2017 5:28 PM 512 CombinedSources07Jun2017.txt
-a---- 2/24/2018 6:29 PM 115 EmpData.csv
-a---- 11/18/2017 6:47 PM 11686 fsoVolume.docx
...
豪华V3和更高。这是本机支持的,例如:
ls -directory
ls -ad
ls -file
ls -af
当然,可以使用if/then或try/catch将上述任何一项设置为仅返回true或false
如果以上所有内容都比您希望的要多键入一些,那么您可以创建自己的函数,并为其指定您选择的任何别名,只要它不是已在使用的别名
请参阅帮助文件
# Get parameters, examples, full and Online help for a cmdlet or function
(Get-Command -Name Get-ChildItem).Parameters
Get-help -Name Get-ChildItem -Examples
Get-help -Name Get-ChildItem -Full
Get-help -Name Get-ChildItem -Online
Get-Help about_*
Get-Help about_Functions
Get-Alias -Definition Get-ChildItem
# Find all cmdlets / functions with a target parameter
Get-Help * -Parameter Append
# All Help topics locations
explorer "$pshome\$($Host.CurrentCulture.Name)"
当然,您也可以检查/修改文件属性。请参阅这篇关于以下主题的文章:
PowerShell中的文件属性
通过PowerShell和DIR命令,轻松使用文件和文件夹属性
因此,您可以这样做,以实现相同的属性检查
Get-ChildItem -Path $FilePath -File -Force | Where {$_.Attributes -notmatch 'ReadOnly'}
或具有别名的函数
Function Test-RegularFile
{
[CmdletBinding()]
[Alias('trf')]
Param
(
[string]$FilePath
)
try
{
Get-ChildItem -Path $FilePath -File -Force `
| Where {$_.Attributes -notmatch 'ReadOnly'}
"$FilePath is a regular file" # success: regular file is readable
}
catch
{
Write-Warning -Message "$FilePath is not a Regular file."
}
}
trf -FilePath D:\Temp\fsoVolume.txt
因为你是一个时尚新手,所以在进行转换比较之前,对转换有一个基本的了解是非常重要的。
有关提供学习PowerShell的一些途径的人员,请参阅本文。
要测试文件是否可读,请尝试打开它。如果你得到一个错误,那么它是不可读的。您需要捕获或捕获异常,或者在出现错误时停止(视情况而定)。请记住,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
或DirectoryInfo
对象(即Get Item
、Get ChildItem
,或表示文件或目录的类似对象的输出),您将拥有PSIsContainer
属性,该属性将告诉您该项是文件还是目录
这可能涵盖99.999%的病例
但是,如果您需要知道某个文件是否是指向某个文件的NTFS硬链接(很少见,但最旧),则会变得更复杂。[很好地描述了前三项。] 让我们创建一个简单的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
和hfile1
都是硬链接,即使file1
不是这样创建的
要清理上述垃圾,请执行以下操作:
Get-ChildItem -Path C:\linktest\ | ForEach-Object { $_.Delete() }
删除某些容器链接会导致命令无法删除这些项
一般解决方案是获取项目并对其进行测试:
# 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
请注意。Windows中没有设备文件类型
对于卷装载点,我不能100%确定它们的外观。我知道您可以在Windows 8.1及更高版本上创建它们,使用Get Partition
,然后是相应的Add PartitionAccessPath
,但我目前使用的是Windows 7。恐怕目前我没有办法测试这个
最后,我不知道Linux上的PowerShell Core 6.0到底是如何处理文件类型的。要测试它是否为常规文件:
Test-Path -PathType Leaf foo.txt
要测试它是否可读,请执行以下操作:
Get-ChildItem foo.txt | ? { $_.Mode -match 'r'}
要测试它是否隐藏,请执行以下操作:
Get-ChildItem -force foo.txt | ? { $_.Mode -match 'h'}
嗯,windows的工作原理与*nix不同。在windows中,文件是常规文件的想法是不存在的。您是在windows或*nix中执行此操作的吗?仅供参考,您的函数可以像
\u ChkRegularFile\u R(){[-f“$1”]&&[-R“$1”];}
那样编写,以澄清:类似POSIX的shell中的文件测试操作符-f
执行隐式符号链接解析;也就是说,如果参数是一个常规文件,或者如果它是一个符号链接,则返回true,如果它的(最终)目标是一个常规文件,则返回true。基本上,我将shell脚本转换为等效的powershell脚本,因此,这些powershell脚本将仅在Windows@ebgreen中运行,这样您就不必担心它是否是常规文件;我建议在命令中使用-LiteralPath
(除了新项
调用,该调用仅支持-Path
,但具有-LiteralPath
语义),以免路径被解释为通配符模式(OP的示例不涉及全局搜索)。一个简单但不太明显的方法来获得一个布尔值,指示文件是否是一个链接:<代码> [BoOL] $ item。LinkType < /C> > @ MKLMunt0当<代码> - LiteralPath <代码>是默认参数而不是<> >路径< /代码>时,我将考虑切换。事实上,我的回答是有教育意义的。为了清晰起见,我在回答中指定了参数并避免使用别名-LiteralPath
被设计为特殊情况,而不是默认情况。您的意思可能是Get ChildItem foo.txt |?{$\.Mode-notmatch'r'}
(r
是只读属性)。但是,这还不足以确定当前用户是否可以读取该文件,因为它的ACL可能会阻止读取。我想知道一个文件是否为常规文件,这个答案恰好显示了最自然的方式,即使它可能没有回答原始问题