我根本不是程序员,但我需要一个 .bat 脚本来做一些事情。其中之一是比较文件。我将有 2 个包含多个 zip 文件的目录,需要对它们进行比较(使用简单的 fc 命令)。
C:\ |__DIR 1
| |_ a.zip
| |_ b.zip
| |_ c.zip
| |_...
|
|__DIR 2
|_ a.zip
|_ b.zip
|_ c.zip
|_...
我将尝试获取变量中的文件,但总是失败...使用时:
SET "dir_A=C:\DIR 1"
SET "dir_B=C:\DIR 2"
for %%a in ("%dir_A%\*.zip") do ( echo %%a )
输出:
C:\DIR 1\a.zip
C:\DIR 1\b.zip
C:\DIR 1\c.zip
使用时:
for /f "delims" %%a in ('dir /b %dir_A%\^*.zip') do ( echo %%a )
输出:
a.zip
b.zip
c.zip
当我使用时:
for /f "delims=" %%a in ('dir /b %dir_A%\^*.zip') do (
set "filename=%%a"
echo %filename%
)
我去拿: 输出
ECHO is off.
ECHO is off.
ECHO is off.
有没有办法将文件放入变量中以便我使用它?我想在 bat 文件中使用它,例如:对于 *.zip 文件 => 文件名...
fc %dir_A%\%filename% %dir_B%\%file > nul
if errorlevel 1 goto error
else...
答案1
CMD 批处理文件中的变量扩展与其他语言的处理方式不同 - 不是作为命令执行的一部分,而是作为解析输入的一部分(即非常早期的阶段,很像 C 预处理器宏)。
因此,%filename%
在读取行时仅扩展一次for
(将整个(...)
组作为一个单元读取) - 此时它扩展为单个字符串 - 尽管变量每次迭代都会发生变化,但命令echo
不会重新扩展。
您可以使用一些解决方法:
改用 PowerShell。它有自己的怪癖(有时您仍然需要用 调用 Cmd
cmd /c
),但总体而言,它的行为更接近标准语言。$dirA = "C:\foo" get-childitem -recurse "$dirA\*.zip" | foreach-object { $file = $_ $filename = $_.Name echo "Got '$filename' which was last touched $($file.LastWriteTime)" }
改用 Python。
from pathlib import Path dirA = Path("C:/foo") for item in dirA.glob("*.zip"): print(f"Got {item.name} (at {item})")
不要使用组,而是
(...)
将操作移到它们自己的下面:label
,然后就可以call
像子程序一样了。(不要忘记让它在最后跳转到 :EOF。)@echo off & setlocal for [...] do call :HandleFile "%%~a" goto :EOF :HandleFile set fullpath=%1 set filename=%~nx1 echo Got %filename% (full path %fullpath%) goto :EOF
启用“延迟扩展”,这将激活第二这种扩展的使用
!variable!
在过程的后期发生。(有时它会带来麻烦,因为它甚至会应用于 % 扩展的结果!)@echo off & setlocal enabledelayedexpansion for [...] do ( set fullpath=%%a set filename=%%~nxa echo Got !filename! (full path !fullpath!). )
答案2
1.你不需要使用此转义^
在^*.zip
, 去掉它。
for /f "delims" %%a in ('dir /b %dir_A%\ ^ *.zip') do echo %%a
for /f "delims" %%a in ('dir /b %dir_A%\*.zip') do echo %%a
2.您正在使用名称中带有空格的文件夹(),因此请使用双引号。DirSpace1
""
for /f "delims" %%a in ('dir /b %dir_A%\*.zip') do echo %%a
for /f "delims" %%a in ('dir /b "%dir_A%\*.zip"') do echo %%a
3.删除分隔符的正确方法是使用=
=>"delims="
或delims^= %%...
:
for /f "delims?" %%a in ('dir /b %dir_A%\*.zip') do echo %%a
for /f "delims=" %%a in ('dir /b "%dir_A%\*.zip"') do echo %%a
:: or..
for /f delims^= %%a in ('dir /b "%dir_A%\*.zip"') do echo %%a
4.您正在将文件值保存在变量中,并始终在循环中将其替换为新名称,建议您假设一个可以在名称中递增的名称,以便在循环中逐个文件分配值,这会很有用,但这会使事情变得有点复杂:
@echo off && setlocal
set "_dir_A=C:\DIR 1"
set "_dir_B=C:\DIR 2"
set /a "_cnt=0, _ledz=1000"
for /f delims^= %%G in =;(' @where.exe "%_Dir_A%:*.zip" ');= do =;(
2>nul where.exe "%_Dir_B%:%%~nxG" 1>nul && =;(
@call set^ /a "_num=%%_ledz%%+%%_cnt%%"
@call set^ "_A_%%_num:~-3%%=%%~nxG"
@call set^ /a "_cnt+=1"
);= || call %:^O "%%~G"
);=
call set^ /a "_cnt-=1"
for /l %%L in =;( 0, 1,%_cnt%);= do call set^ /a "_x=%%_ledz%%+%%~L" && =;(
"%ComSpec%" /v:on /q /s /c "echo/File !_x:~-3!: "!_A_%%_x:~-3%%!"" );=
%:^O
if "%~nx1" == "" endlocal && goto =:eof
echo/ERROR: "%%_Dir_B%%\%~nx1" & exit /b
其他资源: