51

The obvious

ls -dR

does not work.

I am currently using

find /path/ -type d -ls

but the output is not what I need (plain listing of sub-folders)

Is there a way out?

  • Here's a nice bash script to print a directory tree, with colors: mama.indstate.edu/users/ice/bash/btree Easy to install, no root access needed. – aap Sep 12 '15 at 14:29
  • 1
    The real question should be: Why does ls -dR not work? – mastaBlasta Oct 1 '15 at 14:39
  • The real question should include a description of "work", so that we can answer why ls -dR "does not work". ls -dR actually does what the documentation says: "-d Directories are listed as plain files (not searched recursively)." ls -R on the other hand does list subdirectories recursively. – LarsH Apr 23 '18 at 19:51
72

Assuming you just want the name of each directory:

find /path/ -type d -print
| improve this answer | |
  • 9
    +1. BTW, the '-print' arg is optional - it's default. also if a specific listing format is required it can be fed into xargs to run ls with any desired options, e.g. find /path/ -type d -print0 | xargs -0 -r ls -ld. Note the -print0 for NULL terminated output, and the matching -0 xargs arg. – cas Jul 23 '12 at 10:36
  • And if you by chance are running this on Windows and cygwin, then Windows already has a find command, so you probably should specify the path to cygwin's bin folder. – phyatt Apr 27 '15 at 19:39
12

I was looking for the same thing in the past and found this:

tree.sh

#!/bin/sh
#######################################################
#  UNIX TREE                                                            
#  Version: 2.3                                       
#  File: ~/apps/tree/tree.sh                          
#                                                     
#  Displays Structure of Directory Hierarchy          
#  -------------------------------------------------  
#  This tiny script uses "ls", "grep", and "sed"      
#  in a single command to show the nesting of         
#  sub-directories.  The setup command for PATH       
#  works with the Bash shell (the Mac OS X default).  
#                                                     
#  Setup:                                             
#     $ cd ~/apps/tree                                
#     $ chmod u+x tree.sh                             
#     $ ln -s ~/apps/tree/tree.sh ~/bin/tree          
#     $ echo "PATH=~/bin:\${PATH}" >> ~/.profile      
#                                                     
#  Usage:                                             
#     $ tree [directory]                              
#                                                     
#  Examples:                                          
#     $ tree                                          
#     $ tree /etc/opt                                 
#     $ tree ..                                       
#                                                     
#  Public Domain Software -- Free to Use as You Like  
#  http://www.centerkey.com/tree  -  By Dem Pilafian  
#######################################################

echo
if [ "$1" != "" ]  #if parameter exists, use as base folder
   then cd "$1"
   fi
pwd
ls -R | grep ":$" |   \
   sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/   /' -e 's/-/|/'
# 1st sed: remove colons
# 2nd sed: replace higher level folder names with dashes
# 3rd sed: indent graph three spaces
# 4th sed: replace first dash with a vertical bar
if [ `ls -F -1 | grep "/" | wc -l` = 0 ]   # check if no folders
   then echo "   -> no sub-directories"
   fi
echo
exit

I wanted one that listed files as well and I learned about sed and wrote this:

fulltree.sh

#!/bin/sh
#############################################
# Script that displays a recursive formatted folder and file listing
# @author Corbin
# @site iamcorbin.net
#Folder Seperator
BREAK='-------------------------------------------------------------------------------------'

#Optional: if a folder is passed as an argument, run fulltree on that folder rather than the current folder
if [ "$1" != "" ]
   then cd "$1"
   fi
pwd

## Recursive Directory Listing with files
 # 1- preserve directories from being removed in 2 & 3
 # 2- strip first 4 columns
 # 3- strip size and date
 # 4- prepend '  -- ' on each line
 # 5- remove '  -- ' from directories
 # 6- remove extra lines
 # 7- Insert a line break after directories
 # 8- Put a | at the beginning of all lines
 # 9- Indent and process 1st level sub dirs
 #10- Indent and process 2nd level sub dirs
ls -Rhl | sed \
    -e 's/^\.\//x x x x 00:00 |-/' \
    -e 's/^\([^\ ]*.\)\{4\}//' \
    -e 's/.*[0-9]\{2\}:[0-9]\{2\}//' \
    -e 's/^/  -- /' \
    -e 's/\ \ --\ \ |-//'  \
    -e '/--\ $/ d' \
    -e '/^[^ ]/ i\'$BREAK \
    -e 's/^/| /' \
| sed -e '/[^/]*\//,/'$BREAK'/ s/^|/\t&/' -e '/^\t/,/'$BREAK'/ s/'$BREAK'/\t&/' -e 's/[^/]*\//\t\| /' \
| sed -e '/[^/]*\//,/'$BREAK'/ s/^\t|/\t&/' -e '/^\t\t/,/'$BREAK'/  s/'$BREAK'/\t&/' -e 's/[^/]*\//\t\t\| /' \
| sed -e '/[^/]*\//,/'$BREAK'/ s/^\t\t/\t&/' -e 's/[^/]*\//\t\t\t\| /'
echo $BREAK
| improve this answer | |
  • ls -R | grep "^[.]/" | sed -e "s/:$//" -e "s/[^/]*[/]/--/g" -e "s/^/ |/" an update to tree.sh I made to handle some edge cases, latest at: centerkey.com/tree – Dem Pilafian Nov 22 '18 at 21:12
10

You can get the "tree" package, on both ArchLinux and Ubuntu it is called "tree"

So that if you're in ~/ , you can do tree -d and get a full directory listing (in a tree structure) for all of what's in ~/

| improve this answer | |
  • I need plain text, new line separated listing of sub-directories, while tree seems to add its "tree" structure. And I can't seem to find a flag to disable it. – Nemo Feb 25 '12 at 23:15
  • 2
    @Capt.Nemo: For a plain listing, use: tree -dfi ... you can add --noreport to suppress the final display of the total directory count. – Peter.O Feb 26 '12 at 1:37
3

The OP doesn't specify what format of output that they want (beyond "plain listing of sub-folders").

[ 15:53. root@prod-2 /var]% ls -lDR | grep ':$' | head
 .:
 ./account:
 ./cache:
 ./cache/coolkey:
 ./cache/fontconfig:
 ./cache/logwatch:
 ./cache/man:
 ./cache/man/X11R6:
 ./cache/man/X11R6/cat1:
 ./cache/man/X11R6/cat2:...

Optionally remove the trailing : with |sed -e 's/:$//' or format it with |awk '{printf("%-92s \n",$0)}' etc.

| improve this answer | |
1

With zsh and glob qualifiers:

print -rl /path/**/*(D/)

to exclude hidden directories:

print -rl /path/**/*(/)
| improve this answer | |
0

For bash:

shopt -s globstar nullglob dotglob
echo /path/**/*/

The last slash / list only directories.

Option globstar activates **.
Option nullglob removes a * that match nothing.
Option dotglob to include files that start with a dot (hidden files)

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.