1*8462SApril.Chin@Sun.COM#!/usr/bin/ksh93 2*8462SApril.Chin@Sun.COM 3*8462SApril.Chin@Sun.COM# 4*8462SApril.Chin@Sun.COM# CDDL HEADER START 5*8462SApril.Chin@Sun.COM# 6*8462SApril.Chin@Sun.COM# The contents of this file are subject to the terms of the 7*8462SApril.Chin@Sun.COM# Common Development and Distribution License (the "License"). 8*8462SApril.Chin@Sun.COM# You may not use this file except in compliance with the License. 9*8462SApril.Chin@Sun.COM# 10*8462SApril.Chin@Sun.COM# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*8462SApril.Chin@Sun.COM# or http://www.opensolaris.org/os/licensing. 12*8462SApril.Chin@Sun.COM# See the License for the specific language governing permissions 13*8462SApril.Chin@Sun.COM# and limitations under the License. 14*8462SApril.Chin@Sun.COM# 15*8462SApril.Chin@Sun.COM# When distributing Covered Code, include this CDDL HEADER in each 16*8462SApril.Chin@Sun.COM# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*8462SApril.Chin@Sun.COM# If applicable, add the following below this CDDL HEADER, with the 18*8462SApril.Chin@Sun.COM# fields enclosed by brackets "[]" replaced with your own identifying 19*8462SApril.Chin@Sun.COM# information: Portions Copyright [yyyy] [name of copyright owner] 20*8462SApril.Chin@Sun.COM# 21*8462SApril.Chin@Sun.COM# CDDL HEADER END 22*8462SApril.Chin@Sun.COM# 23*8462SApril.Chin@Sun.COM 24*8462SApril.Chin@Sun.COM# 25*8462SApril.Chin@Sun.COM# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26*8462SApril.Chin@Sun.COM# Use is subject to license terms. 27*8462SApril.Chin@Sun.COM# 28*8462SApril.Chin@Sun.COM 29*8462SApril.Chin@Sun.COM# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 30*8462SApril.Chin@Sun.COMexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 31*8462SApril.Chin@Sun.COM 32*8462SApril.Chin@Sun.COM# Make sure all math stuff runs in the "C" locale to avoid problems 33*8462SApril.Chin@Sun.COM# with alternative # radix point representations (e.g. ',' instead of 34*8462SApril.Chin@Sun.COM# '.' in de_DE.*-locales). This needs to be set _before_ any 35*8462SApril.Chin@Sun.COM# floating-point constants are defined in this script). 36*8462SApril.Chin@Sun.COMif [[ "${LC_ALL}" != "" ]] ; then 37*8462SApril.Chin@Sun.COM export \ 38*8462SApril.Chin@Sun.COM LC_MONETARY="${LC_ALL}" \ 39*8462SApril.Chin@Sun.COM LC_MESSAGES="${LC_ALL}" \ 40*8462SApril.Chin@Sun.COM LC_COLLATE="${LC_ALL}" \ 41*8462SApril.Chin@Sun.COM LC_CTYPE="${LC_ALL}" 42*8462SApril.Chin@Sun.COM unset LC_ALL 43*8462SApril.Chin@Sun.COMfi 44*8462SApril.Chin@Sun.COMexport LC_NUMERIC=C 45*8462SApril.Chin@Sun.COM 46*8462SApril.Chin@Sun.COMfunction fatal_error 47*8462SApril.Chin@Sun.COM{ 48*8462SApril.Chin@Sun.COM print -u2 "${progname}: $*" 49*8462SApril.Chin@Sun.COM exit 1 50*8462SApril.Chin@Sun.COM} 51*8462SApril.Chin@Sun.COM 52*8462SApril.Chin@Sun.COM 53*8462SApril.Chin@Sun.COMfunction do_directory 54*8462SApril.Chin@Sun.COM{ 55*8462SApril.Chin@Sun.COM nameref tree=$1 56*8462SApril.Chin@Sun.COM typeset basedir="$2" 57*8462SApril.Chin@Sun.COM 58*8462SApril.Chin@Sun.COM typeset basename 59*8462SApril.Chin@Sun.COM typeset dirname 60*8462SApril.Chin@Sun.COM typeset i 61*8462SApril.Chin@Sun.COM typeset dummy 62*8462SApril.Chin@Sun.COM 63*8462SApril.Chin@Sun.COM typeset -A tree.files 64*8462SApril.Chin@Sun.COM typeset -A tree.dirs 65*8462SApril.Chin@Sun.COM 66*8462SApril.Chin@Sun.COM find "${basedir}"/* -prune 2>/dev/null | while read i ; do 67*8462SApril.Chin@Sun.COM dirname="$(dirname "$i")" 68*8462SApril.Chin@Sun.COM basename="$(basename "$i")" 69*8462SApril.Chin@Sun.COM 70*8462SApril.Chin@Sun.COM # define "node" 71*8462SApril.Chin@Sun.COM if [[ -d "$i" ]] ; then 72*8462SApril.Chin@Sun.COM typeset -C tree.dirs["${basename}"] 73*8462SApril.Chin@Sun.COM nameref node=tree.dirs["${basename}"] 74*8462SApril.Chin@Sun.COM typeset -C node.flags 75*8462SApril.Chin@Sun.COM node.flags.dir="true" 76*8462SApril.Chin@Sun.COM node.flags.file="false" 77*8462SApril.Chin@Sun.COM else 78*8462SApril.Chin@Sun.COM typeset -C tree.files["${basename}"] 79*8462SApril.Chin@Sun.COM nameref node=tree.files["${basename}"] 80*8462SApril.Chin@Sun.COM typeset -C node.flags 81*8462SApril.Chin@Sun.COM 82*8462SApril.Chin@Sun.COM node.flags.dir="false" 83*8462SApril.Chin@Sun.COM node.flags.file="true" 84*8462SApril.Chin@Sun.COM fi 85*8462SApril.Chin@Sun.COM 86*8462SApril.Chin@Sun.COM # basic attributes 87*8462SApril.Chin@Sun.COM typeset -C node.paths=( 88*8462SApril.Chin@Sun.COM dirname="${dirname}" 89*8462SApril.Chin@Sun.COM basename="${basename}" 90*8462SApril.Chin@Sun.COM path="${i}" 91*8462SApril.Chin@Sun.COM ) 92*8462SApril.Chin@Sun.COM 93*8462SApril.Chin@Sun.COM nameref nflags=node.flags 94*8462SApril.Chin@Sun.COM [[ -r "$i" ]] && nflags.readable="true" || nflags.readable="false" 95*8462SApril.Chin@Sun.COM [[ -w "$i" ]] && nflags.writeable="true" || nflags.writeable="false" 96*8462SApril.Chin@Sun.COM [[ -x "$i" ]] && nflags.executable="true" || nflags.executable="false" 97*8462SApril.Chin@Sun.COM 98*8462SApril.Chin@Sun.COM [[ -b "$i" ]] && nflags.blockdevice="true" || nflags.blockdevice="false" 99*8462SApril.Chin@Sun.COM [[ -c "$i" ]] && nflags.characterdevice="true" || nflags.characterdevice="false" 100*8462SApril.Chin@Sun.COM [[ -S "$i" ]] && nflags.socket="true" || nflags.socket="false" 101*8462SApril.Chin@Sun.COM 102*8462SApril.Chin@Sun.COM [[ -L "$i" ]] && nflags.symlink="true" || nflags.symlink="false" 103*8462SApril.Chin@Sun.COM 104*8462SApril.Chin@Sun.COM integer node.size 105*8462SApril.Chin@Sun.COM integer node.links 106*8462SApril.Chin@Sun.COM typeset -C node.owner 107*8462SApril.Chin@Sun.COM ( [[ -x /usr/bin/runat ]] && ls -@ade "$i" || ls -lade "$i" ) | 108*8462SApril.Chin@Sun.COM IFS=' ' read \ 109*8462SApril.Chin@Sun.COM node.mask \ 110*8462SApril.Chin@Sun.COM node.links \ 111*8462SApril.Chin@Sun.COM node.owner.uid \ 112*8462SApril.Chin@Sun.COM node.owner.gid \ 113*8462SApril.Chin@Sun.COM node.size \ 114*8462SApril.Chin@Sun.COM dummy 115*8462SApril.Chin@Sun.COM 116*8462SApril.Chin@Sun.COM typeset -C node.extended_attributes 117*8462SApril.Chin@Sun.COM if [[ ${node.mask} == ~(Er)@ ]] ; then 118*8462SApril.Chin@Sun.COM node.extended_attributes.hasattrs="true" 119*8462SApril.Chin@Sun.COM typeset -a attrlist=( 120*8462SApril.Chin@Sun.COM $( runat "$i" "ls -1" ) 121*8462SApril.Chin@Sun.COM ) 122*8462SApril.Chin@Sun.COM else 123*8462SApril.Chin@Sun.COM node.extended_attributes.hasattrs="false" 124*8462SApril.Chin@Sun.COM fi 125*8462SApril.Chin@Sun.COM 126*8462SApril.Chin@Sun.COM if ${nflags.readable} ; then 127*8462SApril.Chin@Sun.COM # note that /usr/xpg4/bin/file does not use $'\t' as seperator - we 128*8462SApril.Chin@Sun.COM # have to use ':' instead. 129*8462SApril.Chin@Sun.COM file -h "$i" | IFS=' ' read dummy node.filetype 130*8462SApril.Chin@Sun.COM fi 131*8462SApril.Chin@Sun.COM 132*8462SApril.Chin@Sun.COM if ${nflags.dir} ; then 133*8462SApril.Chin@Sun.COM do_directory "${!node}" "$i" 134*8462SApril.Chin@Sun.COM fi 135*8462SApril.Chin@Sun.COM done 136*8462SApril.Chin@Sun.COM 137*8462SApril.Chin@Sun.COM # remove empty lists 138*8462SApril.Chin@Sun.COM (( ${#tree.files[@]} == 0 )) && unset tree.files 139*8462SApril.Chin@Sun.COM (( ${#tree.dirs[@]} == 0 )) && unset tree.dirs 140*8462SApril.Chin@Sun.COM 141*8462SApril.Chin@Sun.COM return 0 142*8462SApril.Chin@Sun.COM} 143*8462SApril.Chin@Sun.COM 144*8462SApril.Chin@Sun.COM 145*8462SApril.Chin@Sun.COMfunction pathtovartree 146*8462SApril.Chin@Sun.COM{ 147*8462SApril.Chin@Sun.COM nameref tree=$1 148*8462SApril.Chin@Sun.COM typeset basedir="$2" 149*8462SApril.Chin@Sun.COM 150*8462SApril.Chin@Sun.COM do_directory tree "${basedir}" 151*8462SApril.Chin@Sun.COM 152*8462SApril.Chin@Sun.COM return 0 153*8462SApril.Chin@Sun.COM} 154*8462SApril.Chin@Sun.COM 155*8462SApril.Chin@Sun.COMfunction usage 156*8462SApril.Chin@Sun.COM{ 157*8462SApril.Chin@Sun.COM OPTIND=0 158*8462SApril.Chin@Sun.COM getopts -a "${progname}" "${filetree1_usage}" OPT '-?' 159*8462SApril.Chin@Sun.COM exit 2 160*8462SApril.Chin@Sun.COM} 161*8462SApril.Chin@Sun.COM 162*8462SApril.Chin@Sun.COM# program start 163*8462SApril.Chin@Sun.COMbuiltin basename 164*8462SApril.Chin@Sun.COMbuiltin cat 165*8462SApril.Chin@Sun.COMbuiltin dirname 166*8462SApril.Chin@Sun.COMbuiltin date 167*8462SApril.Chin@Sun.COMbuiltin uname 168*8462SApril.Chin@Sun.COM 169*8462SApril.Chin@Sun.COMtypeset progname="${ basename "${0}" ; }" 170*8462SApril.Chin@Sun.COM 171*8462SApril.Chin@Sun.COMtypeset -r filetree1_usage=$'+ 172*8462SApril.Chin@Sun.COM[-?\n@(#)\$Id: filetree1 (Roland Mainz) 2008-10-14 \$\n] 173*8462SApril.Chin@Sun.COM[-author?Roland Mainz <roland.mainz@sun.com>] 174*8462SApril.Chin@Sun.COM[-author?Roland Mainz <roland.mainz@nrubsig.org>] 175*8462SApril.Chin@Sun.COM[+NAME?filetree1 - file tree demo] 176*8462SApril.Chin@Sun.COM[+DESCRIPTION?\bfiletree1\b is a small ksh93 compound variable demo 177*8462SApril.Chin@Sun.COM which accepts a directory name as input, and then builds tree 178*8462SApril.Chin@Sun.COM nodes for all files+directories and stores all file attributes 179*8462SApril.Chin@Sun.COM in these notes and then outputs the tree in the format 180*8462SApril.Chin@Sun.COM specified by viewmode (either "list", "namelist" or "tree")..] 181*8462SApril.Chin@Sun.COM 182*8462SApril.Chin@Sun.COMviewmode dirs 183*8462SApril.Chin@Sun.COM 184*8462SApril.Chin@Sun.COM[+SEE ALSO?\bksh93\b(1), \bfile\b(1)] 185*8462SApril.Chin@Sun.COM' 186*8462SApril.Chin@Sun.COM 187*8462SApril.Chin@Sun.COMwhile getopts -a "${progname}" "${filetree1_usage}" OPT ; do 188*8462SApril.Chin@Sun.COM# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 189*8462SApril.Chin@Sun.COM case ${OPT} in 190*8462SApril.Chin@Sun.COM *) usage ;; 191*8462SApril.Chin@Sun.COM esac 192*8462SApril.Chin@Sun.COMdone 193*8462SApril.Chin@Sun.COMshift $((OPTIND-1)) 194*8462SApril.Chin@Sun.COM 195*8462SApril.Chin@Sun.COMtypeset viewmode="$1" 196*8462SApril.Chin@Sun.COMshift 197*8462SApril.Chin@Sun.COM 198*8462SApril.Chin@Sun.COMif [[ "${viewmode}" != ~(Elr)(list|namelist|tree) ]] ; then 199*8462SApril.Chin@Sun.COM fatal_error $"Invalid view mode \"${viewmode}\"." 200*8462SApril.Chin@Sun.COMfi 201*8462SApril.Chin@Sun.COM 202*8462SApril.Chin@Sun.COMtypeset -C myfiletree 203*8462SApril.Chin@Sun.COM 204*8462SApril.Chin@Sun.COMwhile (( $# > 0 )) ; do 205*8462SApril.Chin@Sun.COM print -u2 -f "# Scanning %s ...\n" "${1}" 206*8462SApril.Chin@Sun.COM pathtovartree myfiletree "${1}" 207*8462SApril.Chin@Sun.COM shift 208*8462SApril.Chin@Sun.COMdone 209*8462SApril.Chin@Sun.COMprint -u2 $"#parsing completed." 210*8462SApril.Chin@Sun.COM 211*8462SApril.Chin@Sun.COMcase "${viewmode}" in 212*8462SApril.Chin@Sun.COM list) 213*8462SApril.Chin@Sun.COM set | egrep "^myfiletree\[" | fgrep -v ']=$' 214*8462SApril.Chin@Sun.COM ;; 215*8462SApril.Chin@Sun.COM namelist) 216*8462SApril.Chin@Sun.COM typeset + | egrep "^myfiletree\[" 217*8462SApril.Chin@Sun.COM ;; 218*8462SApril.Chin@Sun.COM tree) 219*8462SApril.Chin@Sun.COM printf "%B\n" myfiletree 220*8462SApril.Chin@Sun.COM ;; 221*8462SApril.Chin@Sun.COM *) 222*8462SApril.Chin@Sun.COM fatal_error $"Invalid view mode \"${viewmode}\"." 223*8462SApril.Chin@Sun.COM ;; 224*8462SApril.Chin@Sun.COMesac 225*8462SApril.Chin@Sun.COM 226*8462SApril.Chin@Sun.COMprint -u2 $"#done." 227*8462SApril.Chin@Sun.COM 228*8462SApril.Chin@Sun.COMexit 0 229*8462SApril.Chin@Sun.COM# EOF. 230