I want to print a directory tree excluding a folder. I already know the basic way to print the tree like this:
tree /A > tree.txt
I want to achieve something like this:
tree /A [exclude folder node_modules] > tree.txt
cmd.exe
's internal tree
command does not support excluding directories.
If you only need to exclude directories by name themselves and not also their entire subtree (child directories and their descendants), see nferrell's answer.
If you need to exclude the entire subtree of directories matching a given name, more work is needed - see below.
Below is the source code for PowerShell function tree
, which emulates the behavior of cmd.exe
's tree
command, while also:
offering selective exclusion of subtrees by name
Note: You may specify multiple names separated by ,
and the names can be wildcard patterns - note that they only apply to the directory name, however, not the full path.
offering cross-platform support
Note: Be sure to save your script with UTF-8 encoding with BOM for the script to function properly without -Ascii
.
offering switch -IncludeFiles
to also print files.
With the function below loaded, the desired command looks like this:
tree -Exclude node_modules -Ascii > tree.txt
Run tree -?
or Get-Help tree
for more information.
### `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
}
In Powershell, just use Where-Object and exclude the folder names you want (put a *
wildcard on the front since it can be difficult to know how many spaces and special characters are on the same line as the folder name):
tree /A | Where-Object {$_ -notlike "*node_modules"} > tree.txt
Edit: This won't exclude subfolders though, it will only exclude the folders you name in the Where-Object clause.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With