Установить рекурсивную глубину для команды dir в dos

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

dir /b /s /AD > c:tempdir_list.txt

это дает мне почти список, который мне нужен. Но это слишком много данных, потому что некоторые папки имеют очень много подпапок, которые я не хочу видеть в своем списке.

возможно ли ограничить глубину рекурсии команды ,скажем, - 3?

c:dir_1dir_2dir_3dir_foo

поэтому, если я выполняю команду в приведенном выше примере в c:> я не хочу видеть каталог dir_foo, но просто в dir_n из них...

может быть, без пакетного / VB-скрипта?

4 ответов


Я уверен, что можно написать сложную команду, которая перечислит n уровней каталогов. Но было бы трудно запомнить синтаксис и ошибок. Она также должна меняться каждый раз, когда вы хотите изменить количество уровней.

гораздо лучше использовать простой скрипт.

изменить 5 лет - на самом деле, есть простой один лайнер, который был доступен с Vista. см. мой новый ROBOCOPY решение.

вот пакетное решение, которое выполняет первый список глубины. Команда DIR/S выполняет первый список ширины, но я предпочитаю этот формат глубины.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1

:procFolder
pushd %1 2>nul || exit /b
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do (
    echo %%~fF
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

первая версия ширины почти такая же, за исключением того, что она требует дополнительного цикла.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1

:procFolder
pushd %1 2>nul || exit /b
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do echo %%~fF
  for /d %%F in (*) do (
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

оба скрипта ожидают два аргумента:

arg1 = путь к корневому каталогу, который будет указан

arg2 = количество уровней для список.

Итак, чтобы перечислить 3 уровня текущего каталога, вы можете использовать

listDirs.bat . 3

чтобы перечислить 5 уровней другого каталога, вы можете использовать

listDirs.bat "d:\my folder\" 5

после всего этого времени (5 лет), и я только что наткнулся на простую командную строку одного лайнера, который был доступен все это время. ROBOCOPY была стандартной утилитой Windows с Vista и доступна для XP через набор ресурсов Windows.

robocopy . . /l /s /njh /njs /ns /lev:4 >c:\temp\dir_list.txt

объяснение

    /L :: List only - don't copy, timestamp or delete any files.
    /S :: copy Subdirectories, but not empty ones.
  /NJH :: No Job Header.
  /NJS :: No Job Summary.
   /NS :: No Size - don't log file sizes.
/LEV:n :: only copy the top n LEVels of the source directory tree.

на /lev:n опция включает корень в count, и вы хотите 3 уровня подкаталога, поэтому я добавил 1 к значению.

обработка далее

выход не идеален в том, что корневая папка включена в выход, и каждый путь включает фиксированную ширину ведущих пробелов. Вы можете удобно устранить корневой путь, а также ведущие пробелы с помощью FOR /F.

(for /f "skip=2 tokens=*" %A in ('robocopy . . /l /s /njh /njs /ns /lev:4') do @echo %A) >c:\temp\dir_list.txt

на ROBOCOPY вывод включает начальную пустую строку, поэтому skip должно быть 2 вместо 1.

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

(for /f "skip=2 tokens=*" %A in ('robocopy . . /l /s /njh /njs /ns /lev:4') do @for %B in ("%A.") do @echo %~fB) >c:\temp\dir_list.txt

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


вот решение, которое основано на решении глубины первого листинга @dbenham,
и позволяет установить минимальный уровень как хорошо.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1
set minLevel=%3
if not defined minLevel set minLevel=0

:procFolder
pushd %1 2>nul || exit /b
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do (
    if %currentLevel% geq %minLevel% echo %%~FF
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

чтобы установить минимальный уровень, просто укажите его как 3-й параметр.
Например: чтобы перечислить от уровня 2 до уровня 5, Вы можете использовать

listDirs.bat target_path 5 2

кроме того, вы можете перечислить с базового уровня, оставив этот параметр пустым

listDirs.bat target_path 5

Это небольшое улучшение по сравнению с решением dbenham (и elady). Он отступает выход согласно глубине. это значительно повышает читаемость.

@echo off
setlocal
set currentLevel=0
set maxLevel=%2
if not defined maxLevel set maxLevel=1
set minLevel=%3
if not defined minLevel set minLevel=0

:procFolder
pushd %1 2>nul || exit /b
set "indent=."
if %currentLevel% lss %maxLevel% (
  for /d %%F in (*) do (
    for /l %%i in (1,1,%currentLevel%) do echo|set /p=%indent%
    if %currentLevel% geq %minLevel% echo %%~fF
    set /a currentLevel+=1
    call :procFolder "%%F"
    set /a currentLevel-=1
  )
)
popd

можно установить символ отступа в set "indent ...