#!/usr/bin/ksh93 # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant export PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin # Make sure all math stuff runs in the "C" locale to avoid problems # with alternative # radix point representations (e.g. ',' instead of # '.' in de_DE.*-locales). This needs to be set _before_ any # floating-point constants are defined in this script). if [[ "${LC_ALL}" != "" ]] ; then export \ LC_MONETARY="${LC_ALL}" \ LC_MESSAGES="${LC_ALL}" \ LC_COLLATE="${LC_ALL}" \ LC_CTYPE="${LC_ALL}" unset LC_ALL fi export LC_NUMERIC=C function fatal_error { print -u2 "${progname}: $*" exit 1 } function do_directory { nameref tree=$1 typeset basedir="$2" typeset basename typeset dirname typeset i typeset dummy typeset -A tree.files typeset -A tree.dirs find "${basedir}"/* -prune 2>/dev/null | while read i ; do dirname="$(dirname "$i")" basename="$(basename "$i")" # define "node" if [[ -d "$i" ]] ; then typeset -C tree.dirs["${basename}"] nameref node=tree.dirs["${basename}"] typeset -C node.flags node.flags.dir="true" node.flags.file="false" else typeset -C tree.files["${basename}"] nameref node=tree.files["${basename}"] typeset -C node.flags node.flags.dir="false" node.flags.file="true" fi # basic attributes typeset -C node.paths=( dirname="${dirname}" basename="${basename}" path="${i}" ) nameref nflags=node.flags [[ -r "$i" ]] && nflags.readable="true" || nflags.readable="false" [[ -w "$i" ]] && nflags.writeable="true" || nflags.writeable="false" [[ -x "$i" ]] && nflags.executable="true" || nflags.executable="false" [[ -b "$i" ]] && nflags.blockdevice="true" || nflags.blockdevice="false" [[ -c "$i" ]] && nflags.characterdevice="true" || nflags.characterdevice="false" [[ -S "$i" ]] && nflags.socket="true" || nflags.socket="false" [[ -L "$i" ]] && nflags.symlink="true" || nflags.symlink="false" integer node.size integer node.links typeset -C node.owner ( [[ -x /usr/bin/runat ]] && ls -@ade "$i" || ls -lade "$i" ) | IFS=' ' read \ node.mask \ node.links \ node.owner.uid \ node.owner.gid \ node.size \ dummy typeset -C node.extended_attributes if [[ ${node.mask} == ~(Er)@ ]] ; then node.extended_attributes.hasattrs="true" typeset -a attrlist=( $( runat "$i" "ls -1" ) ) else node.extended_attributes.hasattrs="false" fi if ${nflags.readable} ; then # note that /usr/xpg4/bin/file does not use $'\t' as seperator - we # have to use ':' instead. file -h "$i" | IFS=' ' read dummy node.filetype fi if ${nflags.dir} ; then do_directory "${!node}" "$i" fi done # remove empty lists (( ${#tree.files[@]} == 0 )) && unset tree.files (( ${#tree.dirs[@]} == 0 )) && unset tree.dirs return 0 } function pathtovartree { nameref tree=$1 typeset basedir="$2" do_directory tree "${basedir}" return 0 } function usage { OPTIND=0 getopts -a "${progname}" "${filetree1_usage}" OPT '-?' exit 2 } # program start builtin basename builtin cat builtin dirname builtin date builtin uname typeset progname="${ basename "${0}" ; }" typeset -r filetree1_usage=$'+ [-?\n@(#)\$Id: filetree1 (Roland Mainz) 2008-10-14 \$\n] [-author?Roland Mainz ] [-author?Roland Mainz ] [+NAME?filetree1 - file tree demo] [+DESCRIPTION?\bfiletree1\b is a small ksh93 compound variable demo which accepts a directory name as input, and then builds tree nodes for all files+directories and stores all file attributes in these notes and then outputs the tree in the format specified by viewmode (either "list", "namelist" or "tree")..] viewmode dirs [+SEE ALSO?\bksh93\b(1), \bfile\b(1)] ' while getopts -a "${progname}" "${filetree1_usage}" OPT ; do # printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" case ${OPT} in *) usage ;; esac done shift $((OPTIND-1)) typeset viewmode="$1" shift if [[ "${viewmode}" != ~(Elr)(list|namelist|tree) ]] ; then fatal_error $"Invalid view mode \"${viewmode}\"." fi typeset -C myfiletree while (( $# > 0 )) ; do print -u2 -f "# Scanning %s ...\n" "${1}" pathtovartree myfiletree "${1}" shift done print -u2 $"#parsing completed." case "${viewmode}" in list) set | egrep "^myfiletree\[" | fgrep -v ']=$' ;; namelist) typeset + | egrep "^myfiletree\[" ;; tree) printf "%B\n" myfiletree ;; *) fatal_error $"Invalid view mode \"${viewmode}\"." ;; esac print -u2 $"#done." exit 0 # EOF.