打印目录树,但在Windows cmd上排除文件夹

时间:2017-05-05 16:48:46

标签: windows powershell command-line

我想打印一个不包含文件夹的目录树。我已经知道打印树的基本方法如下:

tree /A > tree.txt

我想实现这样的目标:

tree /A [exclude folder node_modules] > tree.txt

3 个答案:

答案 0 :(得分:8)

cmd.exe的内部tree命令支持排除目录。

  • 如果您只需按名称排除目录自己他们的整个子树 (子目录及其后代),请参阅nferrell's answer

  • 如果您需要排除与给定名称相匹配的整个子树 ,则需要做更多工作 - 见下文

以下是PowerShell函数tree的源代码,它模拟了cmd.exe tree命令的行为,同时还包括:

  • 按名称选择性排除子树 注意:您可以指定由,分隔的多个名称,名称可以是通配符模式 - 请注意,它们仅适用于目录 name ,但不是完整路径。

  • 提供跨平台支持
    注意:请确保使用带有BOM 的UTF-8编码保存脚本,以使脚本在没有-Ascii的情况下正常运行。

  • 提供开关-IncludeFiles以打印文件

在加载下面的函数时,所需的命令如下所示:

tree -Exclude node_modules -Ascii > tree.txt

运行tree -?Get-Help tree以获取更多信息。

### `tree` source code (add to your `$PROFILE`, for instance; PSv4+):

function tree {
  <#
  .SYNOPSIS
  Prints a directory's subtree structure, optionally with exclusions.                        #'

  .DESCRIPTION
  Prints a given directory's subdirectory structure recursively in tree form,
  so as to visualize the directory hierarchy similar to cmd.exe's built-in
  'tree' command, but with the added ability to exclude subtrees by directory
  names.

  NOTE: Symlinks to directories are not followed; a warning to that effect is
        issued.

  .PARAMETER Path
  The target directory path; defaults to the current directory.
  You may specify a wildcard pattern, but it must resolve to a single directory.

  .PARAMETER Exclude
  One or more directory names that should be excluded from the output; wildcards
  are permitted. Any directory that matches anywhere in the target hierarchy
  is excluded, along with its subtree.
  If -IncludeFiles is also specified, the exclusions are applied to the files'
  names as well.

  .PARAMETER IncludeFiles
  By default, only directories are printed; use this switch to print files
  as well.

  .PARAMETER Ascii
  Uses ASCII characters to visualize the tree structure; by default, graphical
  characters from the OEM character set are used.

  .PARAMETER IndentCount
  Specifies how many characters to use to represent each level of the hierarchy.
  Defaults to 4.

  .PARAMETER Force
  Includes hidden items in the output; by default, they're ignored.

  .NOTES
  Directory symlinks are NOT followed, and a warning to that effect is issued.

  .EXAMPLE
  tree

  Prints the current directory's subdirectory hierarchy.

  .EXAMPLE
  tree ~/Projects -Ascii -Force -Exclude node_modules, .git

  Prints the specified directory's subdirectory hierarchy using ASCII characters
  for visualization, including hidden subdirectories, but excluding the
  subtrees of any directories named 'node_modules' or '.git'.

  #>

    [cmdletbinding(PositionalBinding=$false)]
    param(
      [parameter(Position=0)]
      [string] $Path = '.',
      [string[]] $Exclude,
      [ValidateRange(1, [int]::maxvalue)]
      [int] $IndentCount = 4,
      [switch] $Ascii,
      [switch] $Force,
      [switch] $IncludeFiles
    )

    # Embedded recursive helper function for drawing the tree.
    function _tree_helper {

      param(
        [string] $literalPath,
        [string] $prefix
      )

      # Get all subdirs. and, if requested, also files.
      $items = Get-ChildItem -Directory:(-not $IncludeFiles) -LiteralPath $LiteralPath -Force:$Force

      # Apply exclusion filter(s), if specified.
      if ($Exclude -and $items) {
        $items = $items.Where({ $name = $_.Name; -not $Exclude.Where({ $name -like $_ }, 'First') })
      }

      if (-not $items) { return } # no subdirs. / files, we're done

      $i = 0
      foreach ($item in $items) {
        $isLastSibling = ++$i -eq $items.Count
        # Print this dir.
        $prefix + $(if ($isLastSibling) { $chars.last } else { $chars.interior }) + $chars.hline * ($indentCount-1) + $item.Name
        # Recurse, if it's a subdir (rather than a file).
        if ($item.PSIsContainer) {
          if ($item.LinkType) { Write-Warning "Not following dir. symlink: $item"; continue }
          $subPrefix = $prefix + $(if ($isLastSibling) { $chars.space * $indentCount } else { $chars.vline + $chars.space * ($indentCount-1) })
          _tree_helper $item.FullName $subPrefix
        }
      }
    } # function _tree_helper

    # Hashtable of characters used to draw the structure
    $ndx = [bool] $Ascii
    $chars = @{
      interior = ('├', '+')[$ndx]
      last = ('└', '\')[$ndx]                                                                #'
      hline = ('─', '-')[$ndx]
      vline = ('│', '|')[$ndx]
      space = ' '
    }

    # Resolve the path to a full path and verify its existence and expected type.
    $literalPath = (Resolve-Path $Path).Path
    if (-not $literalPath -or -not (Test-Path -PathType Container -LiteralPath $literalPath) -or $literalPath.count -gt 1) { throw "'$Path' must resolve to a single, existing directory."}

    # Print the target path.
    $literalPath

    # Invoke the helper function to draw the tree.
    _tree_helper $literalPath

  }

答案 1 :(得分:1)

这不完全是一个完整的答案,但应该让你通过一点点工作来完成你想要的。如果您使用PowerShell Community Extensions中的Show-Tree代码作为基础,然后添加了一些内容来过滤掉文件夹,那么您可以完成您想要的任务。这应该是完全可行的,实际上,因为这一小段代码显示了如何定义要排除的字符串(以-like格式接受的通配符),然后获得递归文件夹结构并表示是否是排除文件夹,或包含在排除的文件夹中。

$DirExcludes = @()
$ToExclude = 'temp*'
GCI -Recurse -Directory |%{
    Switch($_){
        {$_.Name -ilike $ToExclude} {
            $DirExcludes += $_.FullName;
            Write-Host $_.FullName -ForegroundColor Red
            Continue}
        {$DirExcludes -and $_.FullName -match "^($(($DirExcludes|%{[regex]::Escape($_)}) -join '|'))"} {
            Write-Host $_.FullName -ForegroundColor DarkRed
            Continue
            }
        default {Write-Host $_.FullName -ForegroundColor Blue}
    }
}

当我针对我的用户个人资料运行时,它显示它同时捕获了'Temp'文件夹和'Template'文件夹,并标记了要排除的那些文件夹和每个子文件夹。您应该能够通过执行以下操作获取Show-Tree命令的代码:

Get-Command Show-Tree -ShowCommandInfo | % Definition

然后你只需要设计如何将类似于我上面的内容合并到该代码中,并且你可以创建一个新功能来实现你想要的东西。

答案 2 :(得分:1)

在Powershell中,只需使用Where-Object并排除所需的文件夹名称(在前面放置一个*通配符,因为很难知道在同一行上有多少空格和特殊字符与文件夹名称):

tree /A | Where-Object {$_ -notlike "*node_modules"} > tree.txt

编辑:这不会排除子文件夹,但它只会排除您在Where-Object子句中命名的文件夹。