对于 FOR 循环中的目录,“%~zI”究竟是啥?

Posted

技术标签:

【中文标题】对于 FOR 循环中的目录,“%~zI”究竟是啥?【英文标题】:What exactly is “%~zI” expanded to for directories in FOR loops?对于 FOR 循环中的目录,“%~zI”究竟是什么? 【发布时间】:2018-11-01 03:32:18 【问题描述】:

来自FOR /?

In addition, substitution of FOR variable references has been enhanced.
You can now use the following optional syntax:

    %~I         - expands %I removing any surrounding quotes (")
    %~fI        - expands %I to a fully qualified path name
    %~dI        - expands %I to a drive letter only
    %~pI        - expands %I to a path only
    %~nI        - expands %I to a file name only
    %~xI        - expands %I to a file extension only
    %~sI        - expanded path contains short names only
    %~aI        - expands %I to file attributes of file
    %~tI        - expands %I to date/time of file
    %~zI        - expands %I to size of file
    %~$PATH:I   - searches the directories listed in the PATH
                   environment variable and expands %I to the
                   fully qualified name of the first one found.
                   If the environment variable name is not
                   defined or the file is not found by the
                   search, then this modifier expands to the
                   empty string

我已经运行了一个 Windows 批处理脚本,它在 FOR 循环中执行 @echo %~aI %~fI ^<%~zI byte^(s^)^> 循环遍历目录(每个目录的路径都存储在 %I 中)并得到以下输出:

d--hs------ J:\$RECYCLE.BIN  <0 byte(s)>
d---------- J:\Multimedia  <4096 byte(s)>
dr--------- J:\-C-\……\Desktop  <12288 byte(s)>
dr--------- J:\-C-\……\Documents  <28672 byte(s)>
dr--------- J:\-C-\……\Downloads  <81920 byte(s)>

上述目录的“大小”与其中的文件无关。 %~zI 的“大小”到底是什么意思?如果%I 是一个普通文件,它将是它的大小。但是如果%I 是一个目录呢?我不能完全掌握它。真的没有意义吗?

【问题讨论】:

它是这样一个目录中使用的磁盘区域的大小,它总是cluster大小的倍数(通常是4K)。目录区域由 目录条目 组成,每个文件对应一个,但在删除文件时该大小不会缩小。 每个目录条目在 FAT32 磁盘中的长度为 32 字节。当目录中的文件数超过一个簇时,会为其分配一个新的4K簇。 请注意,替换不仅适用于 FOR 循环,还适用于函数和命令行参数,如 %~dp0 【参考方案1】:

这是目录条目消耗的空间

目录实际上是一个包含其他文件和目录的特殊文件,因此它必须在某处存储该列表以及必要的元数据。一些文件系统会分配正常的集群并将元数据存储在该数据区域中

NTFS 对大文件夹也是如此。但是在 NTFS 中,小文件也可以stay resident in the MFT entry,这就是为什么您可以看到一些零字节文件夹,因为它们不需要为目录元数据单独分配块

包含这些元数据的流的名称是$I30

在目录的情况下,没有默认的数据流,但是有默认的目录流。目录是流类型$INDEX_ALLOCATION$INDEX_ALLOCATION(目录流)类型的默认流名称为$I30

5.1 NTFS Streams

您可以使用fsutil file layout &lt;directory_path&gt; 进行检查并查看$I30 流。例如,这是我的 PC 的输出。注意%~zIfsutil 输出中的相同大小。大小为 0 的文件夹仅包含一个很小的 ​​$INDEX_ROOT 流,而其他文件夹则有另一个 $INDEX_ALLOCATION,其大小与 %~zI 的输出大小相同

PS C:\> cmd /c "for /d %I in (*) do @echo %~aI %~fI  ^<%~zI byte^(s^)^>"
d---------- C:\ESD  <0 byte(s)>
d---------- C:\Intel  <0 byte(s)>
d---------- C:\PerfLogs  <0 byte(s)>
dr--------- C:\Program Files  <8192 byte(s)>
dr--------- C:\Program Files (x86)  <4096 byte(s)>
dr--------- C:\Users  <4096 byte(s)>
d---------- C:\Windows  <16384 byte(s)>
d---------- C:\Windows.old  <4096 byte(s)>

PS C:\> foreach ($f in ls -Attr Directory) 
>>     $fileLayout = (fsutil file layout $f) -join "`0"
>>     $result = (([regex]'\$I30.*?(?=Stream|$)').Matches($fileLayout)) -split "`0" | Select-String -Pattern '\$I30|  Size'
>>     echo "================================ $f"; $result
>> 
================================ ESD

$I30:$INDEX_ROOT
    Size                : 48
================================ Intel
$I30:$INDEX_ROOT
    Size                : 368
================================ PerfLogs
$I30:$INDEX_ROOT
    Size                : 48
================================ Program Files
$I30:$INDEX_ROOT
    Size                : 168
$I30:$INDEX_ALLOCATION
    Size                : 8,192
$I30:$BITMAP
    Size                : 8
================================ Program Files (x86)
$I30:$INDEX_ROOT
    Size                : 56
$I30:$INDEX_ALLOCATION
    Size                : 4,096
$I30:$BITMAP
    Size                : 8
================================ Users
$I30:$INDEX_ROOT
    Size                : 56
$I30:$INDEX_ALLOCATION
    Size                : 4,096
$I30:$BITMAP
    Size                : 8
================================ Windows
$I30:$INDEX_ROOT
    Size                : 432
$I30:$INDEX_ALLOCATION
    Size                : 16,384
$I30:$BITMAP
    Size                : 8
================================ Windows.old
$I30:$INDEX_ROOT
    Size                : 56
$I30:$INDEX_ALLOCATION
    Size                : 4,096
$I30:$BITMAP
    Size                : 8

ls -l 显示的大小不是目录内文件的总大小时,*nix 也会发生同样的情况:

What does size of a directory mean in output of ls -l command? Why is the size of a directory always 4096 bytes in unix? How is a directory a "special type of file"? What is directory entry?

在 C++17 中有std::filesystem::directory_entry 获取目录信息

【讨论】:

以上是关于对于 FOR 循环中的目录,“%~zI”究竟是啥?的主要内容,如果未能解决你的问题,请参考以下文章

JSF 中的值转换究竟是啥时候发生的?

泛型中的 TEKV?等等,究竟是啥?

下一代操作系统究竟是啥模样

请问SAP中的统驭科目究竟是啥意思?

Instagram 端点的参数究竟是啥:/tags/tag-name/media/recent

请高手解答在windows7中的为此网络启用联邦信息处理标准(FIPS)兼容究竟是啥意思