如何设置Windows命令DIR的递归深度?

szqfcxe2  于 2023-01-10  发布在  Windows
关注(0)|答案(6)|浏览(281)

我目前正在使用以下命令列出一些目录:

dir /b /s /AD > c:\temp\dir_list.txt

这几乎给了我所需要的列表,但是数据太多了,因为有些文件夹有很多子文件夹,我不想在列表中看到。
是否可以将命令的递归深度限制为3(例如)?

c:\dir_1\dir_2\dir_3\dir_foo

因此,如果在c:\>中执行上面示例中的命令,我不希望看到dir_foo目录,而只希望看到dir_n目录。
也许没有批处理或VB脚本?

6ovsh4lw

6ovsh4lw1#

我相信写一个复杂的命令列出n级目录是可能的,但是很难记住语法并且容易出错,而且每次你想改变目录的层数时,它也需要改变。
使用简单的脚本要好得多。

5年后编辑*-实际上,从Vista开始就有一个简单的一行程序。See my new ROBOCOPY solution. *

这是一个执行深度优先列表的批处理解决方案。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

广度优先版本几乎相同,只是需要一个额外的FOR循环。

@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

两个脚本都需要两个参数:
arg 1 =要列出的根目录的路径
arg 2 =要列出的级别数。
因此,要列出当前目录的3个级别,您可以使用

listDirs.bat . 3

要列出不同目录的5个级别,可以使用

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

r7s23pms2#

经过这么长时间(5年),我刚刚偶然发现了一个简单的命令行一行程序,它一直都是可用的。ROBOCOPY从Vista开始就是一个标准的Windows实用程序,可以通过Windows资源工具包提供给XP。

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选项在计数中包括根目录,并且您需要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

但是这个命令的输入有点笨拙。将这个技术合并到一个以根路径和级别作为参数的实用程序批处理文件中应该是很容易的。如果你将命令放在一个批处理脚本中,你必须记住将百分比加倍。

44u64gxh

44u64gxh3#

这里是基于@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

要设置最低水平,只需将其作为第三个参数提供。
例如:要从级别2到级别5列出,您可以使用

listDirs.bat target_path 5 2

或者,您可以通过将此参数留空从基本级别列出

listDirs.bat target_path 5
gr8qqesn

gr8qqesn4#

这比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 ...中设置缩进字符

agyaoht7

agyaoht75#

我的改进版本优于elady的版本:

  • 默认情况下,minLevel为maxLevel-1
  • 更改参数顺序:maxLevel,minLevel,curFolder.这样默认target_path为当前路径,更方便.可以用3种不同的方式调用:
  • listDirs.bat 2(垂直向上)
  • listDirs.bat 2 0(不同的最低级别,请尝试并查看)
  • listDirs.bat 2 0 target_path(需要时提供完整语法)
@echo off
setlocal
set currentLevel=0
set maxLevel=%1
if not defined maxLevel set maxLevel=1
set minLevel=%2
if not defined minLevel set /a minLevel=%maxLevel%-1

:procFolder
pushd %3 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 %maxLevel% %minLevel% "%%F"
    set /a currentLevel-=1
  )
)
popd
uubf1zoe

uubf1zoe6#

set "drive=C:" 
for /F "usebackq tokens=* delims=" %%a in (`PowerShell.exe -Command "&{Get-ChildItem -Path %drive% -Exclude *Recycle* -Recurse -Depth 2 -Name -Directory}"`) do ( 
    echo.[%%a] 
)
  • 深度2将限制文件夹递归到从根目录开始的3个文件夹的深度。-Exclude Recycle 将不显示$Recycle.bin文件夹。-Name使命令显示文件夹的裸名称;不是也去警局。

相关问题