为什么我的 IF 比较运算失败?

发布于 2024-10-27 08:34:09 字数 2203 浏览 2 评论 0原文

更新已解决 - 问题不在于我的代码。命令处理器中存在设计限制(有些人可能会说“错误”)。 IF 比较运算符不适用于高于 2147483648 的值。现在我只需找出如何去掉一些最低有效数字的解决方法。感谢大家的阅读。

=======

你好,在 Cyber​​land,

我管理一家小公司的网络。我正在尝试使用在服务器上运行的批处理文件来设置自动归档过程,并且需要一些逻辑帮助。我不是程序员,没有时间学习 PowerShell 或 VBscript。我已经阅读并重新阅读了有关 IF、FOR 和 CALL 的 MS 命令参考,但无法弄清楚我做错了什么。

我们有一台带有两个磁盘驱动器和一个磁带驱动器的 Windows 2000 Server。一个磁盘有一个共享文件夹,称之为Public;另一个磁盘不共享,称为暂存。

公共驱动器将接受来自客户端桌面的传入备份。我需要将文件从公共驱动器移动到临时驱动器,直到驱动器太满而无法接受更多文件,然后开始磁带备份。磁带运行完成后,暂存驱动器将被清空,并且该过程将恢复将文件从公共移动到暂存。

目标是自动且永久地将桌面备份文件存档到磁带,除了更换磁带之外无需用户干预。

您可能会问,为什么要涉及两个驱动器?有两个原因:

1) 如果桌面直接备份到临时驱动器,则在某些时候客户端桌面备份将因目标驱动器上空间不足而失败。我无法预测这种情况何时会发生;我能想到的唯一可定义条件是可用磁盘空间的任意阈值,但由于要归档的备份文件大小不同,我可能会遇到目标驱动器可用空间高于阈值的情况,但下一个备份超出了该空间。结果:客户端桌面备份失败,服务器磁带备份未启动。

2) 如果临时驱动器已满并且磁带备份因某种原因失败(磁带未更改或其他原因),则将桌面备份到公共驱动器可以为我赢得一些时间,以便在桌面备份开始失败之前解决磁带问题。

这是我正在尝试编码的算法:

1)开始

2)获取临时驱动器上的可用空间

3)获取公共驱动器上最小文件的大小(如果不存在文件,则退出)

4)将文件大小与临时驱动器上的可用空间进行比较驱动器

5) 如果文件适合,则将其移至暂存驱动器;否则,退出并启动磁带备份

6) 返回到开始

这是我的批处理代码,该代码不起作用。在测试的这一阶段,我在公共驱动器中有一个文件 (8 GB),该文件将适合临时驱动器上的可用空间 (32 GB)。 set 命令确认变量已按预期设置;该过程在语句 [ if %BKFsize% LSS %DiskFree%" ] 处失败。不是移动文件,而是调用“else”指定的磁带例程:

@echo off
setlocal enableextensions enabledelayedexpansion
:Begin
REM   obtain and display free space on Staging drive.
D:
for /f "tokens=3 delims= " %%A in ('dir ^| find "bytes free"') do (
set Z=%%A
set Z=!Z:,=!
)
set DiskFree=!Z!
echo.
echo D: has %DiskFree% bytes free
echo.
REM   obtain sizes of files on Public drive to be moved.
E:
cd \backup.email
if not exist *.bkf exit
dir *.bkf /b /os > BKFlist.txt
for /f "tokens=*" %%G in (BKFlist.txt) do call :CheckBKF "%%G"
goto :eof
:CheckBKF
set BKFfile=%1
set BKFsize=%~z1
echo.
echo File %BKFfile% is %BKFsize% bytes
echo.
set
pause
REM   move file(s) to Staging drive, space permitting; or, 
REM   if not enough space for smallest file, start tape backup.
if %BKFsize% LSS %DiskFree% (
echo Moving file %BKFfile% to drive D
echo.
move E:\backup.email\%BKFfile% D:\backup.email
) else (
C:\WINNT\AutoBackup\TapeBKF.cmd
exit
)
goto Begin
:End

我知道这一定相当简单,但就像我说的,我不是程序员,非常感谢您的高超技能,非常感谢您。

update SOLVED - the problem is not with my code. there is a design limitation (some might say "bug") in the command processor. the IF comparison operators do not work with values higher than 2147483648. now I just have to figure out how to strip off some of the least significant digits for the workaround. thanks to all for reading.

=======

hello out there in cyberland,

I manage a small company's network. I'm trying to set up an automated archival process using a batch file running on a server, and need a little help with the logic. I'm not a programmer and don't have the time to learn PowerShell or VBscript. I have read and re-read the MS command reference on IF, FOR, and CALL, and can not figure out what I'm doing wrong.

We have a Windows 2000 Server with two disk drives and a tape drive. One disk has a shared folder, call it Public; the other disk is not shared, call it Staging.

The Public drive will accept incoming backups from the client desktops. I need the process to move files from the Public drive to the Staging drive until the drive is too full to accept any more files, whereupon the tape backup starts. Upon completion of the tape run, the Staging drive will be emptied and the process will resume moving files from Public to Staging.

The goal is to automatically and perpetually archive the desktop backup files to tape, with no user intervention other than changing the tape.

You may ask, why involve two drives? Two reasons:

1) If the desktops back up directly to the Staging drive, at some point the client desktop backups will fail for lack of space on the target drive. I have no way to predict when this will occur; the only definable condition I can think of would be an arbitrary threshold of free disk space, but since the backup files to be archived will be different sizes, I could run into a situation where the target drive free space is above the threshold, but the next backup exceeds that space. Result: client desktop backup fails and server tape backup does not start.

2) If the Staging drive fills up and the tape backup fails for some reason (tape not changed or whatever), having the desktops back up to the Public drive buys me some time to fix the tape issue before the desktop backups begin to fail.

Here is the algorithm I'm trying to code:

1) Begin

2) Obtain free space on Staging drive

3) Obtain size of smallest file on Public drive (if no files present, exit)

4) Compare file size with free space on Staging drive

5) if file will fit, move it to Staging drive; else, exit and start Tape Backup

6) return to Begin

And here is my batch code which is not working. At this stage in testing, I have one file (8 GB) in the Public drive which will fit in the free space (32 GB) on the Staging drive. The set command confirms the variables are being set as expected; the process is failing at the statement [ if %BKFsize% LSS %DiskFree%" ]. Instead of the file being moved, the tape routine specified by 'else' is called instead:

@echo off
setlocal enableextensions enabledelayedexpansion
:Begin
REM   obtain and display free space on Staging drive.
D:
for /f "tokens=3 delims= " %%A in ('dir ^| find "bytes free"') do (
set Z=%%A
set Z=!Z:,=!
)
set DiskFree=!Z!
echo.
echo D: has %DiskFree% bytes free
echo.
REM   obtain sizes of files on Public drive to be moved.
E:
cd \backup.email
if not exist *.bkf exit
dir *.bkf /b /os > BKFlist.txt
for /f "tokens=*" %%G in (BKFlist.txt) do call :CheckBKF "%%G"
goto :eof
:CheckBKF
set BKFfile=%1
set BKFsize=%~z1
echo.
echo File %BKFfile% is %BKFsize% bytes
echo.
set
pause
REM   move file(s) to Staging drive, space permitting; or, 
REM   if not enough space for smallest file, start tape backup.
if %BKFsize% LSS %DiskFree% (
echo Moving file %BKFfile% to drive D
echo.
move E:\backup.email\%BKFfile% D:\backup.email
) else (
C:\WINNT\AutoBackup\TapeBKF.cmd
exit
)
goto Begin
:End

I know this must be fairly simple but like I said, I'm not a programmer, and I bow to your superior skill. Any advice is much appreciated, and thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

孤独陪着我 2024-11-03 08:34:09

在批处理文件中,字符串和整数类型之间没有真正的区别,但这不是您的问题。

问题是整数只能在 32 位有符号范围内工作。
-2147483648 到 2147483647

但是您的文件大小更大,磁盘空间也更大。
要测试这一点,您可以尝试添加一个。

Set /a myvar=BKFsize+1
Set /a myvar=DiskFree+1

我想你会得到一个错误。

您可以解决这个问题,如果您尝试使用字符串比较,目前您进行了字符串比较,但您的数字长度不同,因此您会得到“不可预测”的结果。
但是,如果您用零调整/填充字符串以使它们具有相同的长度,那么它应该可以工作。

set "strBKSize=000000000000000000%bkSize%"
set "strBKSize=%strBKSize:~-15%"
set "strDisksize=000000000000000000%Disksize%"
set "strDisksize=%strDisksize:~-15%"

或者您尝试通过删除 6 或 9 个数字/字符来不以字节为单位,而是以 MB 或 GB 为单位进行计算。

set BKFsizeGB=%BKFsize:~0,-9%

然后您可以将它们用作数字。

In batch file, there is no real difference between strings and integers types, but that isn't your problem here.

The problem is that integers only works in the 32 bit signed range.
-2147483648 to 2147483647

But your filesize is greater and also your disk space.
To test this you could try to add a one.

Set /a myvar=BKFsize+1
Set /a myvar=DiskFree+1

I suppose you get an error.

You could solve it, if you try to use the string compare, currently you do a string compare but your numbers are not of the same length, so you get "unpredictable" results.
But if you adjust/filling the strings with zeros so they have the same length, it should work.

set "strBKSize=000000000000000000%bkSize%"
set "strBKSize=%strBKSize:~-15%"
set "strDisksize=000000000000000000%Disksize%"
set "strDisksize=%strDisksize:~-15%"

Or you try to calculate not with bytes, but in MB or GB, by removing 6 or 9 numbers/characters.

set BKFsizeGB=%BKFsize:~0,-9%

Then you can use them as numbers.

千と千尋 2024-11-03 08:34:09

也许变量中包含的值不是整数,而是字符串,

我想它正在比较: 8<3 == false

Maybe the values contained in your variables are not integers but strings

I suppose it's comparing: 8<3 == false

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文