для разделения файлов при сравнении файлов

Я совершенно не программист, но мне понадобится .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, например: for *.zipfile => имя файла...

      fc %dir_A%\%filename% %dir_B%\%file > nul
if errorlevel 1 goto error
else...

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 

Дополнительные ресурсы:

Расширения переменных в пакетных файлах 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!).
    )
    
Другие вопросы по тегам