Пакетные файлы: список всех файлов в каталоге с относительными путями - PullRequest
59 голосов
/ 05 декабря 2011

Относительно пакетных файлов Windows: есть ли способ перечислить все файлы (или все определенного типа) в определенном каталоге и его подкаталогах, включая пути относительно текущего (или поискового) каталога в списке?

Например, если мне нужны все файлы .txt в текущем каталоге и подкаталогах с их полными путями, я могу сделать

for /r . %%g in (*.txt) do echo %%g >> C:\temp\test.txt

или

dir *.txt /b /s >> C:\temp\test.txt

и я получу что-то вроде

C:\test\Doc1.txt
C:\test\subdir\Doc2.txt
C:\test\subdir\Doc3.txt

Если я делаю

for /r . %%g in (*.txt) do echo %%~nxg >> C:\temp\test.txt

Я получу что-то вроде

Doc1.txt
Doc2.txt
Doc3.txt

Но я действительно хочу:

Doc1.txt
subdir\Doc2.txt
subdir\Doc3.txt

Возможно ли это?

Если мой пост слишком запутанный: я в основном хочу Список файлов рекурсивно в CLI Linux с указанием пути относительно текущего каталога , но только для Windows.

Ответы [ 5 ]

34 голосов
/ 31 августа 2012

Простейшим (но не самым быстрым) способом итерации дерева каталогов и перечисления относительных путей к файлам является использование FORFILES .

forfiles /s /m *.txt /c "cmd /c echo @relpath"

Относительные пути будут заключены в кавычкиведущий .\ как в

".\Doc1.txt"
".\subdir\Doc2.txt"
".\subdir\Doc3.txt"

Чтобы удалить кавычки:

for /f %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do echo %%~A

Чтобы удалить кавычки и ведущие .\:

setlocal disableDelayedExpansion
for /f "delims=" %%A in ('forfiles /s /m *.txt /c "cmd /c echo @relpath"') do (
  set "file=%%~A"
  setlocal enableDelayedExpansion
  echo !file:~2!
  endlocal
)

или без использования отложенного расширения

for /f "tokens=1* delims=\" %%A in (
  'forfiles /s /m *.txt /c "cmd /c echo @relpath"'
) do for %%F in (^"%%B) do echo %%~F
23 голосов
/ 05 декабря 2011

Вы можете просто получить длину символов текущего каталога и удалить их из вашего абсолютного списка

setlocal EnableDelayedExpansion
for /L %%n in (1 1 500) do if "!__cd__:~%%n,1!" neq "" set /a "len=%%n+1"
setlocal DisableDelayedExpansion
for /r . %%g in (*.log) do (
  set "absPath=%%g"
  setlocal EnableDelayedExpansion
  set "relPath=!absPath:~%len%!"
  echo(!relPath!
  endlocal
)
9 голосов
/ 05 декабря 2011

Этот ответ не будет корректно работать с корневыми путями, содержащими знаки равенства (=).(Спасибо @dbenham за указание на это.)


РЕДАКТИРОВАНИЕ: Исправлена ​​проблема с путями, содержащими !, снова замеченными @dbenham (спасибо!).

В качестве альтернативы вычислению длины и извлечению подстрок вы можете использовать другой подход:

  • сохранить корневой путь;

  • очистить корневой путь от путей к файлам.

Вот моя попытка (которая сработала для меня):

@ECHO OFF
SETLOCAL DisableDelayedExpansion
SET "r=%__CD__%"
FOR /R . %%F IN (*) DO (
  SET "p=%%F"
  SETLOCAL EnableDelayedExpansion
  ECHO(!p:%r%=!
  ENDLOCAL
)

The rПеременная присваивается текущему каталогу. Если текущий каталог не является корневым каталогом диска, он не будет заканчиваться на \, который мы изменяем, добавляя символ. (Больше не так, поскольку скрипт теперь читаетпеременная __CD__, значение которой всегда заканчивается на \ (спасибо @jeb!) вместо CD.)

В цикле мы сохраняем текущий путь к файлу в переменной,Затем мы выводим переменную, удаляя корневой путь по пути.

5 голосов
/ 06 декабря 2011

Конечно, вы можете написать рекурсивный алгоритм в Batch, который дает вам точный контроль над тем, что вы делаете в каждом вложенном подкаталоге:

@echo off
set mypath=
call :treeProcess
goto :eof

:treeProcess
setlocal
for %%f in (*.txt) do echo %mypath%%%f
for /D %%d in (*) do (
    set mypath=%mypath%%%d\
    cd %%d
    call :treeProcess
    cd ..
)
endlocal
exit /b
3 голосов
/ 26 октября 2012
@echo on>out.txt
@echo off
setlocal enabledelayedexpansion
set "parentfolder=%CD%"
for /r . %%g in (*.*) do (
  set "var=%%g"
  set var=!var:%parentfolder%=!
  echo !var! >> out.txt
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...