tree
has a -d
option to "List directories only.
". However, I cannot seem to find an option to "List files only." I have looked through the man page, but I cannot seem to find an option for listing only files.
4 Answers
As others have said in the comments, listing only non-directories doesn't exactly mesh with the purpose of the tree
command.
However, listing only the files in the current directory is not unusual if you're like me and prefer to use a customized tree
over ls
(and maybe you've even aliased ls
to tree
with your preferred flags and arguments).
Leveraging a combination of tree
and grep
will get you what you want:
$ tree -F
.
├── file1.txt
├── file5.txt
├── parent_dir1/
│ ├── child_dir/
│ ├── file2.txt
│ └── file3.txt
└── parent_dir2/
└── child_dir2/
└── file4.txt
4 directories, 4 files
$ tree -FL 1 | grep -v /$
.
├── file1.txt
├── file5.txt
2 directories, 1 file
The 'F' flag causes tree
to append a '/' to directories, and the 'v' flag to grep
inverts the given pattern, which matches all lines ending in '/'.
You'll notice that even the summary at the end is still applicable, despite the fact that the directories aren't actually being displayed.
Once you go more than one level down, the tree structure dominates and things get a bit weird.
$ tree -FL 3 | grep -v /$
.
├── file1.txt
├── file5.txt
│ ├── file2.txt
│ └── file3.txt
└── file4.txt
4 directories, 4 files
EDIT
Also, if the sort of broken tree output bothers you (i.e. the fact that some files are prefaced by the '├─' character instead of the '└─' character, and the multi-level version just seems to trail off...), you can fix this by sorting the output, directories first.
$ tree --dirsfirst -FL 1 | grep -v /$
.
├── file1.txt
└── file5.txt
2 directories, 1 file
$ tree --dirsfirst -FL 3 | grep -v /$
.
│ ├── file2.txt
│ └── file3.txt
│ └── file4.txt
├── file1.txt
└── file5.txt
4 directories, 5 files
I think this actually makes the node-less tree structure more readable, as well.
-
Thanks! It's been so long that I forgot that I asked this (and why I asked this). Your solution seems to work well. I think I was trying to list the full file path of all files in a directory. I've used
find
instead which is probably recommended, but with your answer, I can achieve a similar result withtree -F -f -i | grep -v '[/]$'
. Jun 27, 2016 at 20:29
Consider the following command:
tree -ifF /usr/java/default/jre/lib/images | grep -v '/$'
/usr/java/default/jre/lib/images
/usr/java/default/jre/lib/images/cursors/cursors.properties
/usr/java/default/jre/lib/images/cursors/invalid32x32.gif
/usr/java/default/jre/lib/images/cursors/motif_CopyDrop32x32.gif
/usr/java/default/jre/lib/images/cursors/motif_CopyNoDrop32x32.gif
/usr/java/default/jre/lib/images/cursors/motif_LinkDrop32x32.gif
/usr/java/default/jre/lib/images/cursors/motif_LinkNoDrop32x32.gif
/usr/java/default/jre/lib/images/cursors/motif_MoveDrop32x32.gif
/usr/java/default/jre/lib/images/cursors/motif_MoveNoDrop32x32.gif
/usr/java/default/jre/lib/images/icons/sun-java_HighContrastInverse.png
/usr/java/default/jre/lib/images/icons/sun-java_HighContrast.png
/usr/java/default/jre/lib/images/icons/sun-java_LowContrast.png
/usr/java/default/jre/lib/images/icons/sun-java.png
2 directories, 12 files
The -i
and -f
arguments cause tree
to output full paths on each line, rather than indenting. The -F
argument causes it to append an /
to directory names, which are filtered out by the inverted grep (grep -v '/$'
).
I often use a variant of this to help me impatiently watch the contents of an output directory (and its subdirectories) for activity while running some other command...
watch exec "tree -ifFsD /var/local/myapp/data | grep -v '/$'"
-
Nice! This is more useful than my answer if knowing the path to the file is important; my solution is better for getting a sort of bird's eye view of the leaves of a directory tree. Feb 9, 2019 at 0:19
old thread, but as -F now(?) appends different characters to show file types:
-F Append a
/' for directories, a
=' for socket files, a*' for executable files, a
>' for doors (Solaris) and a `|' for FIFO's, as per ls -F
the command could become:
watch exec "tree -ifFsD /var/local/myapp/data | grep '[[:alnum:]]$\|\*'"
-
this is the same as unix.stackexchange.com/a/460121 - with less detail.– guntbertJul 3, 2020 at 22:32
-
Sorry, didn't get the "same" part as the link points back to this thread.– QippurJul 5, 2020 at 7:45
-
About the lack of details, it is correct. The regular expression in grep command seeks for a letter at the end of the row ( [[:alnum:]]$ ) or ( \| ) an asterisk, which is appended at the end of executable files ( \* ). Pipe is escaped to be treated as an OR, asterisk is escaped not to be treated as special characters of regular expressions.– QippurJul 5, 2020 at 7:53
-
sorry, my bad. I was referring to this answer unix.stackexchange.com/a/460121/29882– guntbertJul 5, 2020 at 9:01
-
If you're OK with an answer that doesn't use tree
, I'd recommend find
.
find $DIR -type f
Where $DIR
is the directory you want to search for.
You could then prettify this into a tree format if you wanted to.
You could create a function tree_file
that did it all. Credit goes to JavaSherrif over at this SO answer (previously linked) for the sed
stuff. I just tweaked it to include UTF characters.
tree_file() {
DIR=${1:-"."}
find $DIR -type f | sed -e "s/[^-][^\/]*\// │/g" -e "s/│\([^ ]\)/│── \1/"
}
find
works, but I'd personally rather do things withtree
since it's much easier for me to use and does not search hidden files/folders automatically.gfind ./ -type f
works much better. I can't even remember why I wanted to usetree
at this point.