如何判断路径是文件还是目录?

How to tell if a path is a file or a directory?

tl;dr:

给定文件系统路径,我如何确定它是指 PowerShell 中的文件还是目录?


首先,我实际上对 Powershell 知之甚少,所以请原谅我在这篇文章中可能表现出的任何无知。

我希望创建一个脚本,只要受监视文件夹中发生更改,它就可以触发进程。我在 Internet 上找到了一个 Powershell 脚本,我认为它给了我一个良好的开端。但是,稍微调整和测试后,我发现它有问题。

该脚本主要是创建一个日志文件并将其附加到受监视的文件夹和子文件夹中,并且看起来运行良好。但是,如果我在子文件夹内进行任何更改,并在日志文件中记录这些更改,它还会在日志文件中添加一行,说明子文件夹本身已更改,就像它是一个文件一样已经改变了。

我需要脚本在文件更改时触发进程,但除了子文件夹内的任何更改触发的进程外,它不得触发额外的进程。我希望你能明白我在这里说的。

因此,我需要一种方法(可以很好地集成到我发现的脚本中)来区分何时更改文件和何时更改文件夹。

脚本(我稍微改编了一下)如下:

### SET FOLDER TO WATCH + FILES TO WATCH + SUBFOLDERS YES/NO
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = "monitoredfolder"
$watcher.Filter = "*.*"
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true  

### DEFINE ACTIONS AFTER AN EVENT IS DETECTED
$action = {
            $path = $Event.SourceEventArgs.FullPath
            $Name = $Event.SourceEventArgs.Name
            $OldName = $Event.SourceEventArgs.OldName
            $OldFullPath = $Event.SourceEventArgs.OldFullPath
            $changeType = $Event.SourceEventArgs.ChangeType
            $logline = "$(Get-Date), $changeType, $OldFullPath, $path, $OldName, $Name"
            Add-content "log.txt" -value $logline
          }    
### DECIDE WHICH EVENTS SHOULD BE WATCHED 
Register-ObjectEvent $watcher "Created" -Action $action
Register-ObjectEvent $watcher "Changed" -Action $action
Register-ObjectEvent $watcher "Deleted" -Action $action
Register-ObjectEvent $watcher "Renamed" -Action $action
while ($true) {sleep 5}

我希望能够在 $action 部分添加一行,这将创建另一个变量,该变量可以作为列添加到日志文件中。纯粹基于猜测,我尝试了以下和其他方法,但它们没有用:

$pathtype = $Event.SourceEventArgs.FullPathType

$pathAttributes = $Event.SourceEventArgs.FullPathAttributes

$Attributes = $Event.SourceEventArgs.Attributes

$IsDirectory = $Event.SourceEventArgs.IsDirectory

老实说,我并没有真正期望它们会起作用,但我想我会试一试。

这里有谁知道“$Event.SourceEventArgs”中第二个点之后的所有内容吗?

我应该采取另一种方法吗?

非常感谢。

 Test-Path -Type Leaf -LiteralPath $Event.SourceEventArgs.FullPath

告诉您路径字符串 $Event.SourceEventArgs.FullPath 是否指的是(现有的)文件,而不是 目录-Type Container).

另一种方法是使用 System.IO.File and the Exists 静态方法。

[System.IO.File]::Exists($Event.SourceEventArgs.FullPath)

我发现在进行基准测试时,它比 Test-Path 快大约 4 倍,无需更多输入。

回答您的另一个问题:Does anyone here know all of the things which can go after the second dot in "$Event.SourceEventArgs."? 您可以通过将对象发送到 Get-Member.

轻松找出对象上可用的属性和方法。

将您的操作更改为

$action = {
            $Event.SourceEventArgs | Get-Member
          }

然后从创建的作业中检索输出将列出对象的属性、方法和类型。

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command                  
--     ----            -------------   -----         -----------     --------             -------                  
3      fe46cc0b-51e...                 NotStarted    False                                ...                      



PS> Get-Job 3 | Receive-Job -Keep


   TypeName: System.IO.FileSystemEventArgs

Name        MemberType Definition                                    
----        ---------- ----------                                    
Equals      Method     bool Equals(System.Object obj)                
GetHashCode Method     int GetHashCode()                             
GetType     Method     type GetType()                                
ToString    Method     string ToString()                             
ChangeType  Property   System.IO.WatcherChangeTypes ChangeType {get;}
FullPath    Property   string FullPath {get;}                        
Name        Property   string Name {get;}