Рекурсивно для цикла в пакетных файлах без следующих символических ссылок - PullRequest
1 голос
/ 28 октября 2019

Есть ли простой способ в пакетных файлах циклически перебирать файлы, включая подкаталоги, например, ниже, кроме без следующих символических ссылок ?

FOR /R %%F IN (*) DO (...)

Я не видел такого флага в for help ...

В контексте я пишу командный файл, который перебирает файлы и создает символические ссылки. Он должен проходить через подкаталоги, однако, когда есть символические ссылки, нацеленные на каталоги, он не должен проходить через них. В моей текущей реализации цикла FOR /R проблема заключается в том, что он обрабатывает такие символические ссылки как подкаталоги и запускает сценарий в содержимом их цели. Мне все равно, исключает ли решение символические ссылки на простые файлы (в отличие от dirs).

Спасибо за вашу помощь

РЕДАКТИРОВАТЬ для уточнения:

Например, при условии, что эта структура каталогов:

dir
 |-- A.txt
 |-- subDir
 |     |-- B.txt
 |-- linkDir = symlink to targetDir
 |-- Z.txt = symlink to targetDir/C.txt

targetDir
 |-- C.txt

Когда я запускаю цикл FOR /R на dir, он обрабатывает A.txt и B.txt, как ожидалось, но также C.txt, которыйЯ не хочуЭто связано с тем, что инструкция FOR /R следует символическим ссылкам при создании списка файлов для повторения, поэтому она действует так, как если бы linkDir был обычным подкаталогом, который содержит C.txt.

Относительно Z.txt, не имеет значения, прочитал ли цикл это. Реализация FOR /R фактически обрабатывает его, но я настроил фильтр для пропуска итерации, когда %%F является символической ссылкой.

Проблема в том, что я не знаю, как сказать FOR не включать C.txt в списке, ни когда %%F равно targetDir\C.txt, как узнать, что этот файл находится в списке, потому что он следовал по символической ссылке в пути dir\subDir\C.txt.

Ответы [ 2 ]

1 голос
/ 28 октября 2019

Попробуйте:

@echo off
setlocal EnableDelayedExpansion

for /R /D %%f in (*) do (
   set "attr=%%~Af"
   if "!attr:~8,1!" neq "l" (
      echo Files in this not-symlink dir:
      dir /B /A:-D "%%f"
   )
)
1 голос
/ 28 октября 2019

Вы можете написать свою собственную функцию рекурсии, проверяя каждый файл / каталог на наличие ссылок.
Это немного медленно, из-за доступа %%~aX к каждому файлу / каталогу.

@echo off

call :recurseDir .
exit /b

:recurseDir
rem echo ----- :recurseDir "%~1" -------
setlocal EnableDelayedExpansion
pushd "%~1"
FOR /F "delims=" %%X in ('dir /b') DO (
    set "attr=%%~aX"

    if "!attr:~8,1!" NEQ "l" (
        if "!attr:~0,1!" EQU "d" (
            call :recurseDir "%%~fX"
        ) ELSE (
            call echo :processFile "%%~fX"
        )
    )
)
popd

Toускорив, вы можете разделить логику для файлов и каталогов.
Тогда нужно только проверять каталоги с %%~aX для символических ссылок.
Эта версия больше не нуждается в отложенном расширении, потому что она обнаруживает символические ссылки путем разделенияатрибуты у символа l в d-------l--.
Поскольку в Win 7 отображается только d-------l, необходимо добавить хотя бы один фиктивный символ к атрибутам (я выбираю #)

@echo off

call :recurseDir .
exit /b

:recurseDir
echo ----- :recurseDir "%~1" -------
pushd "%~1"
FOR /F "delims=" %%X in ('dir /b /a:-l-d 2^> nul') DO (
    call echo :processFile "%%~fX"
)
FOR /D %%X in (*) DO (  
    set "symlink="
    for /F "tokens=2 delims=l" %%A in ("%%~aX #") DO set "symlink=1"
    if not defined symlink (
        call :recurseDir "%%~fX"
    )
)
popd
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...