File: nls.sh 1 #!/bin/sh 2 3 # The MIT License (MIT) 4 # 5 # Copyright (c) 2026 pacman64 6 # 7 # Permission is hereby granted, free of charge, to any person obtaining a copy 8 # of this software and associated documentation files (the "Software"), to deal 9 # in the Software without restriction, including without limitation the rights 10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 # copies of the Software, and to permit persons to whom the Software is 12 # furnished to do so, subject to the following conditions: 13 # 14 # The above copyright notice and this permission notice shall be included in 15 # all copies or substantial portions of the Software. 16 # 17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 # SOFTWARE. 24 25 26 # nls [options...] [files/folders...] 27 # 28 # Nice LS runs `ls` to show files (and folders), then colors folders and links 29 # using ANSI styles to make things easier to scan/read. Long numbers are also 30 # made easier to read using alternating ANSI styles. 31 # 32 # To declutter the output, the `.` and `..` entries are ignored from the `ls` 33 # results. 34 # 35 # Besides the usual `ls`-specific options, this script offers easier-to-use 36 # extra options, where leading double-dashes are also allowed: 37 # 38 # -group, -grouped show folders before regular files and links 39 # -help show this help message 40 # -iso show date/time metadata using the long ISO format 41 # -sort, -sorted reverse-sort results by size 42 43 44 list='ls -al --color=never' 45 46 while [ $# -gt 0 ]; do 47 case "$1" in 48 -group|--group|-grouped|--grouped) 49 list="${list} --group-directories-first"; shift; continue 50 ;; 51 52 --h|-help|--help) 53 awk '/^# +nls /, /^$/ { gsub(/^# ?/, ""); print }' "$0" 54 exit 0 55 ;; 56 57 -iso|--iso) 58 list="${list} --time-style long-iso"; shift; continue 59 ;; 60 61 -sort|--sort|-sorted|--sorted) 62 list="${list} -S"; shift; continue 63 ;; 64 65 --) shift; break ;; 66 67 -*) list="${list} $1"; shift; continue ;; 68 esac 69 70 break 71 done 72 73 less_opts='-MKiCRS' 74 if [ $# -le 1 ]; then 75 less_opts='-MKiCRS --header=1' 76 fi 77 78 restyle=' 79 / \.\.?\/?$/ || /^total / { next } 80 81 { 82 underline = ((n + 1) % 5 == 0 && n != 1) 83 folder = /^d[^ ]+/ 84 link = /^l[^ ]+/ 85 86 gsub(/^(d[^ ]+)/, "\x1b[38;2;0;165;225m&\x1b[0m") 87 gsub(/^(l[^ ]+)/, "\x1b[38;2;0;185;45m&\x1b[0m") 88 if (folder) gsub(/\x1b\[0m/, "\x1b[0m\x1b[38;2;0;165;225m") 89 if (link) gsub(/\x1b\[0m/, "\x1b[0m\x1b[38;2;0;185;45m") 90 if (underline) gsub(/\x1b\[0m/, "\x1b[0m\x1b[4m") 91 92 fmt = underline ? "%5d \x1b[4m%s" : "%5d %s" 93 printf fmt, ++n, $0 94 printf (underline || folder || link) ? "\x1b[0m\n" : "\n" 95 } 96 ' 97 98 l='([0-9]{1,3})' 99 p='([0-9]{3})' 100 s='' 101 r='' 102 alt_digits=' 103 s-'$l$p$p$p$p$p$p'-\1'$s'\2'$r'\3'$s'\4'$r'\5'$s'\6'$r'\7-g; 104 s-'$l$p$p$p$p$p'-\1'$s'\2'$r'\3'$s'\4'$r'\5'$s'\6'$r'-g; 105 s-'$l$p$p$p$p'-\1'$s'\2'$r'\3'$s'\4'$r'\5-g; 106 s-'$l$p$p$p'-\1'$s'\2'$r'\3'$s'\4'$r'-g; 107 s-'$l$p$p'-\1'$s'\2'$r'\3-g; 108 s-'$l$p'-\1'$s'\2'$r'-g; 109 ' 110 111 # show all non-existing files/folders given 112 failed=0 113 for arg in "$@"; do 114 [ "${arg}" = "-" ] && continue 115 [ -e "${arg}" ] && continue 116 printf "no file/folder named \"%s\"\n" "${arg}" >&2 117 failed=1 118 done 119 120 [ "${failed}" -gt 0 ] && exit 2 121 122 gap=0 123 for arg in "${@:-.}"; do 124 arg="$(realpath "${arg}")" 125 [ "${gap}" -gt 0 ] && printf "\n" 126 printf "\033[7m%-80s\033[0m\n\n" "${arg}" 127 gap=1 128 ${list} "${arg}" | sed -E "${alt_digits}" | awk "${restyle}" 129 done | { less ${less_opts} 2> /dev/null || less -RIMS 2> /dev/null || cat; }