批处理文件比较运算符出错

Error with batch file comparison operators

无法解决这个问题,我对批处理脚本不是很熟悉,尽管我会尽可能使用它们。

我有一个脚本可以测试当前文件是否大于 4GB,如果是则执行操作,如果不是则执行另一个操作。

我在 .bat 文件中有以下内容:

 %~d1

set fsize=%~z1

if %fsize% gtr 4000000000 (
    echo "exit"
) ELSE (
    echo "keep going"
)

pause

当我将一个 4.8 GB 的文件拖到这个文件上时,我在命令行中得到了这个结果:

set fsize=4876064456
if 4876064456 GTR 4000000000 (echo "exit" )  ELSE (echo "keep going" )
"keep going"

当我将一个 60 MB 的文件拖到上面时,我得到了这个:

set fsize=61840920

if 61840920 GTR 4000000000 (echo "exit" )  ELSE (echo "keep going" )
"keep going"

如果我将运算符更改为 LSS,则会从两个文件中得到“退出”结果。为什么没有进行适当的比较?

Windows 命令处理器 cmd.exe 使用 C 函数 strtol 将字符串转换为整数以进行整数比较。类型 long int 是一个 32 位有符号整数(并非总是如此,取决于 C 编译器,但用于 cmd.exe 的编译)。因此,值范围限制在 −2^312^31−1−21474836482147483647.

可以绕过此限制来检查文件是否≥4294967296,如以下代码所示:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
if "%~1" == "" echo ERROR: %~nx0 must be run with a file name.& goto EndBatch
if not exist "%~1" echo ERROR: File "%~1" not found.& goto EndBatch
if exist "%~1\" echo ERROR: "%~1" is not a file.& goto EndBatch

set "fsize=%~z1"
if "%fsize:~9,1%" == "" echo File is smaller than 4 GB.& goto EndBatch
if not "%fsize:~10,1%" == "" echo File is larger than 4 GB.& goto EndBatch
if "%fsize%" LSS "4294967296" echo File is smaller than 4 GB.& goto EndBatch
echo File is equal or larger than 4 GB.
:EndBatch
pause
endlocal

如果文件大小字符串少于 10 个字符,则第一个条件为真,这意味着文件大小小于 1000000000 字节。

如果文件大小字符串超过 10 个字符,则第二个条件为真,这意味着文件大小大于 9999999999 字节。

如果用双引号括起来的文件大小 string 恰好有 10 个字符小于 string "4294967296"表示文件大小小于4294967296字节。

有关字符串和整数比较的更多信息,请参阅以下答案:

set "limit=4000000000"
set "zeroes=000000000000000000000000000000000000000000"

set "zlimit=%zeroes%%limit%"
set fsize=%zeroes%%~z1

if "%fsize:~-15%" gtr "%zlimit:~-15%" (...

此处的目的是通过在每个字符串前添加大量零作为前缀,然后比较每个字符串的最后 (15) 个字符,使被比较的两个字符串的长度相等。使用字符串是因为 4G 超出了 cmd 整数的 32 位符号容量。

根据您提供输入参数的方式,以下替代方案可能适合您的目的:

@Echo Off & SetLocal EnableExtensions
Set "Name=%~1"
%SystemRoot%\System32\wbem\WMIC.exe DataFile Where ^
 "FileSize <= '4294967296' And Name='%Name:\=\%'" Get FileSize 2>NUL ^
 | %SystemRoot%\System32\find.exe "FileSize" 1>NUL || Echo Exit /B
Rem Your code here for files not greater than 4 Gibibytes

在上面的示例中,我使用了 Gibibytes,这是 Windows 操作系统倾向于使用其文件大小。如果您更喜欢使用千兆字节,如您提供的示例中所示,请将 4 行的 4294967296 更改为 4000000000,并将 Gibibytes 行的 Gigabytes 更改为16=].