Пакетные файлы: Список всех файлов в каталоге с относительными путями
что касается пакетных файлов Windows: есть ли способ перечислить все файлы (или все определенного типа) в определенном каталоге и его подкаталогах, включая пути относительно текущего (или поиска) каталога в списке?
например, если я хочу, чтобы все txt файлы в текущем каталоге и в подкаталогах с их полными путями, я могу сделать
for /r . %%g in (*.txt) do echo %%g >> C:temptest.txt
или
dir *.txt /b /s >> C:temptest.txt
и я получу что-то вроде
C:testDoc1.txt
C:testsubdirDoc2.txt
C:testsubdirDoc3.txt
Если Я делай
for /r . %%g in (*.txt) do echo %%~nxg >> C:temptest.txt
я получу что-то вроде
Doc1.txt
Doc2.txt
Doc3.txt
но то, что я действительно хочу:
Doc1.txt
subdirDoc2.txt
subdirDoc3.txt
возможно ли это?
если мой пост слишком запутан: я в основном хочу "список файлов рекурсивно в Linux CLI с путем относительно текущего каталога", только для Windows.
5 ответов:
вы можете просто получить длину символа текущего каталога и удалить их из вашего абсолютный список
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 )
самый простой (но не самый быстрый) способ итерации дерева каталогов и списка относительных путей к файлам-использовать 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
этот ответ не будет работать правильно с корневыми путями, содержащими одинаковые знаки (
=
). (Спасибо @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
.)в цикле мы сохраняем текущий путь к файлу в переменную. Затем мы выводим переменную, удаляя корневой путь по пути.
конечно, вы можете написать рекурсивный алгоритм в пакете, который дает вам точный контроль над тем, что вы делаете в каждом вложенном подкаталоге:
@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