# limitations under the License.
-# ls -lA with enhanced formatting
-# octal permissions
-# omited acl type specifier
-# better hard link count: number of subdirectories or number of linked files or omitted if 0
-# better human readable size
-# more natural date/time format for my American raised eyes
ll() {
- local x y z q perm padding line binls sizePadding middle tail size
- local -a lines
+ case $1 in
+ -h|--help)
+ cat <<'EOF'
+usage: ll [ARGS_TO_LS]
+ls -lA with enhanced output
+
+* octal permissions
+* omited acl type specifier
+* better hard link count: number of subdirectories or the
+ number of linked files or omitted if it is 0
+* better human readable size
+* more natural date/time format for my American raised eyes
+* remove first line size summary
+
+EOF
+ ;;
+ esac
+ local x y perm line binls sizePadding middle tail size \
+ max_hl_digits hardlinks initial_space hardlink_spacing
+ local max_hl_digits=0
+ local -a lines hl
binls=$(type -P ls)
- local first=true
local aclchar=false
# there's no way to tell if ls uses the acl specifier unless we loop over the data twice
# the 11th char is either
# + for any other kind of acl
# or blank for no other kind of acl
# I don't want to see this generally.
- while read line; do
- lines+=("$line")
- [[ ! ${line:10:11} == " " ]] && aclchar=true
+ while read -r line; do
+ # if we did want the first line, it would need to be stripped of non-printing chars:
+ #line=${line#$'\E[00m'}
+ # lines like "total 123M", we don't want
+ if [[ ! $line =~ ^total\ [0-9][^\ ]*$ ]]; then
+ lines+=("$line")
+ if ! [[ $line == [-dscbl][-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xtT]* ]]; then
+ hardlinks=
+ else
+ [[ ! ${line:10:1} == " " ]] && aclchar=true
+
+ # we also need to parse the hardlinks on the first pass, because for
+ # example ls could see the highest count as 11, and thus use 3
+ # places for hardlinks, " 10", but then we use 9 or 8 for a more
+ # useful count, and would then use 2 places. So we have to look
+ # through them all because we can't rely on the spacing that ls
+ # decided on.
+ y="${line:11}"
+ initial_space="${y%%[![:space:]]*}"
+ hardlinks="${y#$initial_space}" # remove any initial spaces
+ hardlinks="${hardlinks%%[[:space:]]*}" # remove everything beyond first word
+ # ignore the hardlinks that files/dirs always have
+ hardlinks=$(( hardlinks - 1 ))
+ [[ $hardlinks == 0 ]] && hardlinks=
+ if (( ${#hardlinks} > max_hl_digits )); then
+ max_hl_digits=${#hardlinks}
+ fi
+ fi
+ hl+=("$hardlinks")
+ fi
done< <( "$binls" -lAh --color=always "--time-style=+%m-%d %Y
%m-%d %I:%M %P" "$@" )
-
- for line in "${lines[@]}"; do
- # very first line starts with some non printing chars
- if $first; then
- line=${line#$'\E[00m'}
- first=false
- fi
- if ! [[ $line == [-dscbl][-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xtT]* ]]; then
+
+ hardlink_spacing=$((max_hl_digits + 1))
+
+ for index in "${!lines[@]}"; do
+ line=${lines[index]}
+ hardlinks=${hl[index]}
+ if [[ $line != [-a-zA-Z][-r][-w][-xsS][-r][-w][-xsS][-r][-w][-xtT]* ]]; then
+ # line we don't understand
printf "%s\n" "$line"
- else
- perm=0
- for (( x=0; x<=8; x++ )); do
- y=${line:$(( -1*x + 9 )):1}
- [[ $y == [tT] ]] && perm=$(( perm + 512 ))
- if [[ $y == [sS] ]]; then
- [[ $x == 3 ]] && perm=$(( perm + 1024 ))
- [[ $x == 6 ]] && perm=$(( perm + 2048 ))
- fi
- [[ $y != [-ST] ]] && perm=$(( perm + 2**x ))
- done
- if $aclchar; then
- y="${line:11}"
- else
- y="${line:10}"
- fi
- t="${y#"${y%%[![:space:]]*}"}" # remove any initial spaces
- hardLinks="${t%%[[:space:]]*}" # remove everything beyond first word
- z=$(( ${#y} - ${#t} + ${#hardLinks} )) # length of hardlink string including padding
- middle=${y#*[^ ]* }
- size=${middle#*[^ ]* *[^ ]* }
- middle=${middle%"$size"}
- tail=${size#*[^ ]* }
- size=${size%"$tail"}
- declare -i sizePadding="${#size} - 1"
- size=( $size ) # remove spaces
- size=${size/.?/}
- # ignore the hardlinks that files/dirs always have
- if [[ ${line:0:1} == d ]]; then
- hardLinks=$(( hardLinks - 2 ))
- else
- hardLinks=$(( hardLinks - 1 ))
- fi
- [[ $hardLinks == 0 ]] && hardLinks=
- printf "%s%4o%${z}s%s%${sizePadding}s%s\n" \
- "${line:0:1}" $perm "$hardLinks" " $middle" "$size" " $tail"
+ continue
fi
+ perm=0
+ for (( x=0; x<=8; x++ )); do
+ y=${line:$(( -1*x + 9 )):1}
+ [[ $y == [tT] ]] && perm=$(( perm + 512 ))
+ if [[ $y == [sS] ]]; then
+ [[ $x == 3 ]] && perm=$(( perm + 1024 ))
+ [[ $x == 6 ]] && perm=$(( perm + 2048 ))
+ fi
+ [[ $y != [-ST] ]] && perm=$(( perm + 2**x ))
+ done
+ if $aclchar; then
+ y="${line:11}"
+ else
+ y="${line:10}"
+ fi
+ middle=${y#*[^ ]* }
+ size=${middle#*[^ ]* *[^ ]* }
+ middle=${middle%"$size"}
+ tail=${size#*[^ ]* }
+ size=${size%"$tail"}
+ declare -i sizePadding="${#size} - 1"
+ size=( $size ) # remove spaces
+ size=${size/.?/}
+
+ printf "%s%4o%${hardlink_spacing}s%s%${sizePadding}s%s\n" \
+ "${line:0:1}" $perm "$hardlinks" " $middle" "$size" " $tail"
done
}
-