Windows 相当于 unix 的“stat”命令吗?

Windows 相当于 unix 的“stat”命令吗?

因此,我正在寻找一种命令行方法来获取文件的相对低级元数据的简短文本转储,大致stat与 *nix 系统上的方法相同。

换句话说,通过 Win32 或 NT 文件 API 可以轻松获得的信息,而无需实际读取内容的文件,并且绝对不需要靠近 Shell(如在 Explorer 和保存/打开对话框中所见,以及使用的任何内容shell32.dll)。

在 NTFS 上,此信息将趋向存储在文件的 MFT 条目中,但我听说哪些属性最终出现在 MFT 中在很大程度上取决于哪个属性适合,因为许多属性是可选的、可重复的和/或可变大小的,有些属性可以是,尽管也可以在 MFT 中使用多个插槽。(事实上,如果其他属性不占用太多空间,甚至可以将文件/目录的全部内容存储在 MFT 中!)所以,嗯,显然“出现在 MFT 中”不能用于实际定义我正在寻找什么。

另外,我并不是在寻找能够解析 NTFS 本身或仅适用于 NTFS 文件系统的工具:我只提到 NTFS,因为其他本地 FS 会支持更多特定于 NT 的东西吗?

为了具体起见,下面是stat我用作路由器的 Debian 盒子:

hydrogen% stat .
  File: ‘.’
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: fe00h/65024d    Inode: 507974      Links: 4
Access: (0755/drwxr-xr-x)  Uid: ( 1000/ naesten)   Gid: ( 1000/ naesten)
Access: 2016-08-31 14:12:47.650440935 -0400
Modify: 2016-09-20 17:26:15.935591584 -0400
Change: 2016-09-20 17:26:15.935591584 -0400
 Birth: -
hydrogen%

以下是适用于 Windows 的 Git:

以下“截图”的彩色光栅版本

Sam@Sam-laptop MINGW64 ~
$ git --version
git version 2.8.2.windows.1

Sam@Sam-laptop MINGW64 ~
$ stat .
  File: '.'
  Size: 0               Blocks: 32         IO Block: 65536  directory
Device: 147ac391h/343589777d    Inode: 1970324836977201  Links: 1
Access: (0755/drwxr-xr-x)  Uid: (197608/     Sam)   Gid: (197121/ UNKNOWN)
Access: 2016-09-18 18:32:28.072538600 -0400
Modify: 2016-09-18 18:32:28.072538600 -0400
Change: 2016-09-18 18:32:28.072538600 -0400
 Birth: 2014-08-21 18:52:08.217444400 -0400

Sam@Sam-laptop MINGW64 ~
$

这时,我说“出生”时间戳字段是 Windows 主义,但显然不是相当正确,因为 Debian 的统计数据显示了该字段,但上面显示为空,因为文件系统实际上没有该字段。(这至少比“访问”时间戳要清楚得多:两个系统都没有以传统方式更新这些时间戳strictatime。)

还请注意,Windows 端口如何显示虚构的文件访问权限、一个大得难以置信的“inode 编号”,以及我只能假设也是虚构的 UID/GID 编号(考虑到 NT 使用可变长度的分层标识符而不是固定大小的数字来识别用户和组,并且不允许用户和组同时拥有所有权;也就是说,在 NT 上,一个文件由单个用户或组拥有,其他任何人都只能从 ACL 中获得其权利)。

MS 是否提供了这种工具,大概是显示更多实际信息和较少仙境信息的工具?


我的原文如下:

是的,我知道有 的端口stat,但是(A)我担心,如果出现以下情况,信息可能会被泄露:

  1. 它通常不会出现在 Unixstat输出中
  2. 上游代码中缺少该代码stat(如果有)
  3. 搬运工
    1. 没有注意到 Windows 提供了信息
    2. 正在构建一个无法通过的 POSIX 层
    3. 不确定如何最好地呈现信息(或这样做是否合适)stat
    4. 没有无限的时间

和 (b)我想知道微软是否提供了任何类似的工具。

但实际上,任何通过命令行方式获取的信息stat都可能提供(无论它是否涉及名为的程序stat),以及它提供的或多或少特定于 NTFS 的信息的描述,都会令人感兴趣。

附言我使用的是 Windows 7,但不要因此阻止您提及 Windows 后续版本中首次发布的内容。

答案1

Get-Item /path/to/file | Format-List仅使用本机 Cmdlet 即可获得您所需的内容。

Get-Item获取您感兴趣的文件的详细信息。Format-List这将有点不直观地向 PowerShell 主机公开比在其他情况下看到的更多的参数。它还会将其格式化为列表,正如您预计。

 ~> Get-Item ./temp.txt | Format-List


    Directory: /Users/brianshacklett


Name           : temp.txt
Length         : 989
CreationTime   : 4/5/18 9:52:04 PM
LastWriteTime  : 4/5/18 9:52:04 PM
LastAccessTime : 6/26/18 7:58:18 PM
Mode           : ------
LinkType       :
Target         :
VersionInfo    : File:             /Users/brianshacklett/temp.txt
                 InternalName:
                 OriginalFilename:
                 FileVersion:
                 FileDescription:
                 Product:
                 ProductVersion:
                 Debug:            False
                 Patched:          False
                 PreRelease:       False
                 PrivateBuild:     False
                 SpecialBuild:     False
                 Language:

如果你觉得冗长的内容太过烦人,可以使用别名将其缩短为gi /path to file | fl

答案2

我刚刚编写了一个 PowerShell 脚本。它几乎包含了适用于 Windows 的所有内容,但访问控制除外,访问控制通常太大而无法包含在摘要中。您可以使用该icacls实用程序查看它们。

$obj = $args[0]
If ($obj.GetType().Name -eq 'String') {$obj = gi $obj}
'File: ' + $obj.FullName
'Size: ' + $obj.Length
$extents = [string](fsutil file queryextents "$($obj.FullName)")
If (-$extents.StartsWith('i')) {
  'Clusters: ' + ($extents.Substring(26) -split 'LCN')[0]
  'LCN: ' + $extents.Substring(42)
} Else {
  'Clusters: stored in file table'
}
'Attributes: ' + $obj.Attributes
$volumeinfo = (fsutil fsinfo volumeinfo "$([System.IO.Path]::GetPathRoot($obj.FullName)[0] + ':')")
$volumeinfo | ? {$_.StartsWith('Volume Serial')} | % {$_.Replace(' :', ':')}
$fileid = (fsutil file queryfileid "$($obj.FullName)")
'File ID: ' + $fileid.Substring(11)
$links = (fsutil hardlink list "$($obj.FullName)")
'Links: ' + ([string[]]$links).Length
'Owner: ' + $obj.GetAccessControl().Owner
''
'Access: ' + $obj.LastAccessTime
'Modify: ' + $obj.LastWriteTime
'Create: ' + $obj.CreationTime
'' # Extra blank line for readability

它使用普通的 .NET/PowerShell 文件系统条目属性,并调用fsutil实用程序来处理棘手的内容。由于该实用程序不是 PowerShell cmdlet,因此我不得不进行一些混乱的字符串截断才能获得正确的信息。

要使用它,请将其保存为.ps1文件,然后参阅PowerShell 标签 wiki. 输出示例:

File: C:\Users\Ben\test\blank.ps1
Size: 8
Clusters: stored in file table
Attributes: Archive
Volume Serial Number: 0x9c67b42c
File ID: 0x0000000000000000000700000014428b
Links: 1
Owner: POWERSHELL\Ben

Access: 07/29/2016 20:01:25
Modify: 07/29/2016 20:02:43
Create: 07/29/2016 20:01:25

答案3

没有精确的等效但最近您可以使用 Windows 内置实用程序获得fsutil命令。它将为您提供大部分内容stat,以及有关底层文件系统结构的更详细信息。但不同的是,stat它需要在管理员权限下运行。您还可以使用西米克(或者Get-WmiObjectgwmi别名)PowerShell 版本)获取大量有用数据。对于其他一些选项,您需要使用其他命令获取

以下是如何将类似信息传递给格式选项stat(在 PowerShell 中,如果有 cmd 版本),您可以使用它来自定义输出。否则只需转储fsutil file layout,fsutil fsinfo sectorinfofsutil fsinfo ntfsinfo直接输出

  • 访问权限:Windows 访问权限与 POSIX 访问权限有很大不同。因此,没有与%A。然而确实存在类似的信息

  • 分配的块数(%b):运行fsutil file layout path\to\filefsutil volume filelayout path\to\file并计算流中分配的集群总数$DATA

    例如,对于以下输出,我们分配了 4 个区,每个区的长度分别为 82、432.419、259 和 155.076 个簇。因此,分配的块数为 82 + 432419 + 259 + 155076 = 587836。一个快速技巧是将最后一个簇的 VCN 编号与其长度相加:432760 + 155076 = 587836

      Stream                  : 0x080  ::$DATA
          Attributes          : 0x00000000: *NONE*
          Flags               : 0x00000000: *NONE*
          Size                : 2.407.772.410
          Allocated Size      : 2.407.776.256
          Extents             : 4 Extents
                              : 1: VCN: 0 Clusters: 82 LCN: 1.620.482
                              : 2: VCN: 82 Clusters: 432.419 LCN: 5.331.392
                              : 3: VCN: 432.501 Clusters: 259 LCN: 3.230.067
                              : 4: VCN: 432.760 Clusters: 155.076 LCN: 9.299.239
    
  • %b 报告的每个块的字节大小(%B):

      fsutil fsinfo ntfsinfo <drive> | findstr /c:"Bytes Per Cluster"`
    
  • SELinux 安全上下文字符串(%C): 没有可比特征

  • 设备编号 (%日%D): 没有类似命令,但如果你想获取设备ID,可以使用以下命令

      (Get-WmiObject win32_volume | where { $_.driveletter -eq '<drive>' }).deviceid
    
  • 十六进制的原始模式(%F): 没有等效形式。请参阅上文的 %a/%A

  • 文件类型 (%F): 没有直接等效项,因为 Windows 文件和驱动程序模型非常不同,并且 Windows 上没有字符设备之类的东西,所以您不会得到“字符特殊文件”。但是通常您可以使用(ls path\to\file).Mode来获取文件模式(如上面的 %A),并(ls path\to\file).LinkType获取链接类型

  • 所有者的组名称 (%G):

      (Get-Acl file.ext).Group
    
  • 所有者的组 ID(%G):

      (gwmi win32_useraccount | where { $_.caption -eq "$((Get-Acl file.ext).Group)" }).SID
    
  • 硬链接数(%H): 没有类似的信息。但是fsutil hardlink list path\to\file会打印文件的所有硬链接,因此我们可以轻松地使用

      (fsutil hardlink list path\to\file | Measure-Object).Count
    
    • 或者使用(fsutil file layout path\to\file | sls -CaseSensitive -Pattern '^Link.+\s+:\s+0x[0-9a-f]+:\s*HLINK Name\s+:' | Measure-Object).Count
  • Inode 编号 (%我): Windows 中没有 inode,但 NTFS(以及可能较新的文件系统,如 ReFS)有一个等效的 inode,称为文件 ID可以从fsutil file layout输出中提取,也可以直接使用

      fsutil file queryfileid path\to\file
    
  • 文件名 (%n): 这是很明显的

  • 如果是符号链接(%N),则引用文件名并取消引用:

  • I/O块大小(%o): 看%s对于以下文件系统

  • 总大小,以字节为单位(%s): 。或者可以在cmd的输出(ls path\to\file).Length中轻松看到,并在上面的字段下的输出中dirfsutil file layout path\to\fileSize

  • 设备类型 (%吨%吨): 看%吨对于下面的文件系统类型

  • 所有者的用户名 (%U):

      (Get-Acl path\to\file).Owner
    
  • 所有者的用户 ID(%u): 您可以使用以下命令获取用户 SID

      (gwmi win32_useraccount | where { $_.caption -eq "$((Get-Acl D:\zz.bat).owner)" }).SID
    
  • 文件时间:

    • 上次访问时间(%X):(ls path\to\file).LastAccessTime
    • 获取自纪元以来的上次访问时间(%X):(ls path\to\file).LastAccessTime.Ticks(ls path\to\file).LastAccessTime.ToFileTime()(取决于你想要哪个纪元:1/1/0001 或 1/1/1601)以 100ns 分辨率获取文件时间
    • 同样最后修改时间(%年%Y)可以通过LastWriteTime
    • 获取上次元数据更改时间(%z%Z)比较棘手,您可能需要从 PowerShell 调用 win32 API

对于文件系统,通常可以使用fsutil fsinfo ntfsinfo <drive>fsutil fsinfo sectorinfo <drive>查找详细信息

  • 非超级用户可用的空闲块(%A): 没有等效项。但我认为你可以用fsutil quota query

  • 文件系统中的总数据块数(%b):

      fsutil fsinfo ntfsinfo <drive> | findstr /c:"Number Sectors"
    
  • 文件系统中的文件节点总数(%C): 如果是关于 inode 数量,那么 NTFS 以及许多较新的 Linux 文件系统(如 Btrfs 或 XFS)上没有 MFT 记录限制。MFT 文件大小将增加以存储更多文件记录。可以使用以下命令检查 MFT 记录总数fsutil fsinfo ntfsinfo <drive>

  • 文件系统中的空闲文件节点(%日): 不确定这是什么。如果是关于未使用的 inode 数量,那么如上所述,通常没有上限。可能fsutil volume allocationreport <drive>会起作用

  • 文件系统中的可用块(%F):

    • fsutil fsinfo ntfsinfo <drive> | findstr /c:"Free Clusters"
    • 更多详细信息请访问fsutil volume allocationreport <drive>
  • 十六进制文件系统 ID (%我): 我不知道 Windows 上的确切同义词是什么,但这些可能提供了该信息

      fsutil fsinfo ntfsinfo <drive> | findstr /c:"Resource Manager Identifier" /c:"NTFS Volume Serial Number"
      (gwmi win32_volume | where { $_.driveletter -eq 'd:' }).serialnumber`
    
  • 文件名的最大长度(%升):

      (gwmi win32_volume | where { $_.driveletter -eq <drive>  }).maximumfilenamelength
    
  • 块大小(用于更快的传输)(%s):

      fsutil fsinfo sectorinfo <drive> | findstr /c:"Performance"
    
  • 基本区块大小(用于区块计数)(%S):

      fsutil fsinfo sectorinfo <drive> | sls physical
      fsutil fsinfo ntfsinfo <drive> | sls physical
      (gwmi win32_volume | where { $_.driveletter -eq 'd:' }).blocksize
    
  • 类型:适用于%吨你可以使用fsutil fsinfo volumeinfo <drive> | findstr /c:"File System Name"。我不确定是什么%吨但这似乎是分区的神奇数字

上述命令(Get-WmiObject win32_ALIAS | where { $_.FILTERFIELD -eq 'VALUE' }).GETFIELD可以改为wmic ALIAS where FILTERFIELD='VALUE' get GETFIELD /value。但是wmic已被弃用,因此将来可能会被删除

答案4

您使用的工具使用的环境充当 Windows 和 Linux 之间的薄层,因此需要模拟某些部分才能让 Linux 工具发挥作用。这解释了为什么有一些虚构的信息(希望)以一致的方式匹配。您必须查看实现它的环境的具体情况才能理解它。

另一方面,(对我来说)你正在寻找的并不完全清楚。正如你所说,有各种你不想使用的 API。只有那些“模拟”信息与你相关吗?

否则,您可能需要一系列工具来获取所需的所有信息。据我所知,访问权限和 ACL 在 NTFS 中根深蒂固。诸如 之类的工具icalcs可以帮助您在命令行上获取有关访问权限的信息。要获取更深入的信息(部分信息),您可能需要考虑使用如该示例所示的 WMI。PowerShell 中的简单dirget-childitem可能会为您提供有关创建时间等的更多信息。我不知道有任何内置工具可以为您提供所有这些信息的概述。您可能要做的是使用有关 API 的信息并将它们包装在 PowerShell 脚本中。这可能接近您实际想要执行的操作。我不确定是否已经有脚本可以执行此操作。

相关内容