批处理文件比较运算符出错
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^31 到 2^31−1 即 −2147483648 到 2147483647.
可以绕过此限制来检查文件是否≥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=].
无法解决这个问题,我对批处理脚本不是很熟悉,尽管我会尽可能使用它们。
我有一个脚本可以测试当前文件是否大于 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^31 到 2^31−1 即 −2147483648 到 2147483647.
可以绕过此限制来检查文件是否≥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=].