Have tree hide gitignored files

Tree supports the -I flag.

-I pattern
   Do not list those files that match the wild-card pattern.

Tree supports a single pattern which will exclude all files/directories that match it.

Git's ignore files are a bit more complicated:

Exclusion can come from multiple files, $HOME/.config/git/ignore, the output of git config --get core.excludesfile, .gitignore (per directory), ~/.gitignore, and more (see man gitignore).

Another problem is the patterns that tree supports differs from what git does (as noted by @Brad Urani).

But we can get close-ish ...

tree -I "$(grep -hvE '^$|^#' {~/,,$(git rev-parse --show-toplevel)/}.gitignore|sed 's:/$::'|tr \\n '\|')"

Or as a function:

function gtree {
    git_ignore_files=("$(git config --get core.excludesfile)" .gitignore ~/.gitignore)
    ignore_pattern="$(grep -hvE '^$|^#' "${git_ignore_files[@]}" 2>/dev/null|sed 's:/$::'|tr '\n' '\|')"
    if git status &> /dev/null && [[ -n "${ignore_pattern}" ]]; then
      tree -I "${ignore_pattern}" "${@}"
    else 
      tree "${@}"
    fi
}

This might help: list git ignored files in an almost-compatible way for tree filter:

function tree-git-ignore {
    # tree respecting gitignore

    local ignored=$(git ls-files -ci --others --directory --exclude-standard)
    local ignored_filter=$(echo "$ignored" \
                    | egrep -v "^#.*$|^[[:space:]]*$" \
                    | sed 's~^/~~' \
                    | sed 's~/$~~' \
                    | tr "\\n" "|")
    tree --prune -I ".git|${ignored_filter: : -1}" "$@"
}

Another way is possible if you're using tree 1.8.0 since it supports the --fromfile flag:

   --fromfile  Reads a directory listing from a file rather than the file-system.  Paths provided on the command
   line are files to read from rather than directories to search.  The dot (.)  directory  indicates  that  tree
   should read paths from standard input.

We could use git ls-tree to get all non-git-ignored files in a project, and pipe the output to tree.

Assuming we have a git repository, where ignored files are ignored in .gitignore:

git_repo
├── .gitignore
├── bar
│   ├── b.txt
│   └── ignored
├── foo
│   ├── a.txt
│   └── ignored
└── ignored

The following command:

git ls-tree -r --name-only HEAD | tree --fromfile

Gives:

.
├── .gitignore
├── bar
│   └── b.txt
└── foo
    └── a.txt

2 directories, 3 files

Or if you need a specific path:

git ls-tree -r --name-only HEAD foo | tree --fromfile

Gives:

.
└── a.txt

0 directories, 1 file

Caveats

  • Beware that changes such as deleted or renamed files that haven't already been committed can cause git ls-tree to appear out of sync.

Tags:

Git

Tree