Imported from ../bash-2.0.tar.gz.
[platform/upstream/bash.git] / examples / scripts.v2 / vtree
1 #! /bin/bash
2 #
3 # original from:
4 # vtree: visual directory tree
5 # @(#) vtree.sh 1.1 91/07/01
6 # 90/04 john h. dubois iii (john@armory.com)
7 # 91/07/01 fixed bug that caused problems when dir given on command line,
8 #          added some info to help, changed to 4-space indenting
9 #
10 # conversion to bash v2 syntax done by Chet Ramey
11 #
12 help=\
13 "Syntax: vtree [startdir] [namelen=#] [linelen=#]
14 If startdir is not specified, tree will start at current dir.
15
16 namelen specifies the minimum number of characters of a directory name that
17 are guaranteed to be printed.
18 This is a tradeoff between the number of tree levels that can fit on a
19 screen line and the number of chars of each dir name that can be printed.
20 In most cases it will be possible to print more than namelen characters of
21 the name (a name up to namelen+1 chars will always be printed in full),
22 but in some cases truncation down to namelen chars will occur.
23 If truncation occurs, a '>' is printed at the end of the name.
24 namelen=8 (the default) typically causes about 5 dirs/1000 to be truncated.
25 namelen=7 typically causes about 10 dirs/1000 to be truncated.
26 namelen=8 will allow 6 full length dirs to be printed in 79 columns.
27 namelen=7 will allow 7 full length dirs to be printed in 79 columns;
28
29 linelen specifies the maximum number of characters to print on one screen
30 line.  All characters beyond this are truncated.  The default is 1024.
31 To avoid line wrap on an 80 column terminal with autowrap, use linelen=79.
32 "
33
34 for i in "$@"; do
35     case $i in
36     -h) echo "$help"; exit;;
37     *=*)
38         vars="$vars $i"
39         ;;
40     *)
41         if [ ! -x $i -o ! -d $i ]; then     # arg must be a dir and executable
42             echo "$i: directory not accessible."
43             exit
44         fi
45         cd $i
46         ;;
47     esac
48     shift
49 done
50
51 pwd     # print path of root of tree
52
53 # find all directories depth first; ignore permission errors
54 find . -type d -print 2> /dev/null | \
55 gawk -F/ '
56
57 # Do this block for NR == 1 instead of BEGIN because command line var
58 # assignments are not done until after BEGIN block is executed.
59 NR == 1 {
60     if (namelen)
61         MaxLen = namelen;
62     else
63         MaxLen = 8;
64     if (!linelen)
65         linelen = 1024
66     HSpace = substr("              ",1,MaxLen);     # used to indent tree
67     n = 0;          # number of dirs found on one major branch
68 }
69
70 $0 != "." {     # do for every line produced by find except tree root dir
71     if (NF == 2 && n > 0)   # print major branch whenever a new one starts
72         list();
73     Depth[n] = NF - 1;      # record depth and name of dir
74      Name[n++] = $NF;
75 }
76
77 END {
78     list()  # print last major branch
79 }
80
81 function list() {
82     Line = Name[0];     # initialize first line of branch to be branch base
83     for (i = 1; i < n; i++) {   # for each name in major branch
84         if (Depth[i] == Depth[i-1] + 1)
85             AddHLink(); # if moving deeper into branch, use same line
86         else {
87             print substr(Line,1,linelen);   # last line is done; print it
88             Line = "";  # start new line
89             # print indentation, vert links, and vert/horiz links
90             for (d = 1; d < Depth[i] - 1; d++)  # for each level of indentation
91                 # if a vert. link has been established for this level
92                 if (VLink[d])
93                     Line = Line HSpace " |  ";
94                 else        # print empty indentation
95                     Line = Line HSpace "    ";
96             # Print last part of vert. link
97             if (VLink[d] == i) {
98                 VLink[d] = 0;   # mark level for no vert link
99                 Line = Line HSpace " \\--";
100             }
101             else
102                 Line = Line HSpace " |--";
103         }
104         Line = Line Name[i];    # Add dir name to line
105     }
106     print substr(Line,1,linelen);   # print last line of major branch
107     n = 0;      # reset name counter
108 }
109
110 function AddHLink() {
111     NDepth = Depth[i];  # Depth of this name
112     VLink[NDepth - 1] = 0;
113     # search until a name found at a level less than this one
114     for (j = i + 1; j < n && Depth[j] >= NDepth; j++)
115         # keep track of last name that VLink should connect to
116         if (Depth[j] == NDepth)
117             VLink[NDepth - 1] = j;
118     if (VLink[NDepth - 1]) {
119         NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 1);
120         if (length(NLine) < length(Line))
121             Line = substr(NLine,1,length(NLine) - 1) ">"
122         else
123             Line = NLine;
124         Line = Line substr("--------------+--",
125             18 - ((NDepth - 1) * (MaxLen + 4) - length(Line)));
126     }
127     else {
128         NLine = substr(Line,1,(NDepth - 2) * (MaxLen + 4) + MaxLen + 3);
129         if (length(NLine) < length(Line))
130             Line = substr(NLine,1,length(NLine) - 1) ">"
131         else
132             Line = NLine;
133         Line = Line substr("-----------------",
134             1,(NDepth - 1) * (MaxLen + 4) - length(Line));
135     }
136 }
137 ' $vars