This post is part of an educational series on building a shell script to graphically display the structure of a directory.
Previously
The Script
#!/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
Setup
Directory setup
Please check the first post on the tree command to see our directory setup.
Script setup
I will not add the script to my path as of yet, as we are just testing right now. First let’s add it to where we are testing. Open up vi
and paste. Check here to see how to paste in vi. Exit insert mode and save the file.
[ahmed@amayem .git]$ vi test.sh
[ahmed@amayem .git]$ ./test.sh
-bash: ./test.sh: Permission denied
[ahmed@amayem .git]$ chmod +x test.sh
[ahmed@amayem .git]$ ./test.sh
/home/ahmed/test/.git
.
|-branches
|-hooks
|-info
|-objects
|---info
|---pack
|-refs
|---heads
|---tags
Looks like it’s working.
Script Breakdown
echo
We are printing a new line.
if [ "$1" != "" ] #if parameter exists, use as base folder
then cd "$1"
fi
The $1
variable indicates the first command line argument. For example if we said tree ~
then $1
would equal ~
. So basically we are checking if an argument was given. If one was given then go to it.
pwd
The working directory is printed.
ls -R | grep ":$" |
sed -e 's/:$//' -e 's/[^-][^/]*//--/g' -e 's/^/ /' -e 's/-/|/'
We analyzed this in our previous post.
if [ `ls -F -1 | grep "/" | wc -l` = 0 ] # check if no folders
then echo " -> no sub-directories"
fi
Let’s check the man
page for ls
:
-F, --classify
append indicator (one of */=>@|) to entries
and
-1 list one file per line
Let’s see what we get when we try it by itself:
[ahmed@amayem .git]$ ls -F -1
branches/
config
description
HEAD
hooks/
info/
objects/
refs/
test.sh*
So it added a slash, /
, to the ends of directories, nothing to the end of normal files, and a star, *
, to the end of executables.
grep "/"
The output from the previous ls
command is piped into this grep
command which singles out the directories.
wc -l` = 0
Let’s check the man
page of wc
:
wc - print newline, word, and byte counts for each file
and
-l, --lines
print the newline counts
So we are counting how many directories we have in the working directory. If that number is zero then print out, " -> no sub-directories"
.
echo
Print out a new line.
Next steps
- Modifying the one line command to show files, as well as directories
- Building a new recursive script that looks better and has more functionality
References
- Dem Pilafian on centerkey