用于比较文件的分隔符

用于比较文件的分隔符

我根本不是程序员,但我需要一个 .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 

其他资源:

相关内容