Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Wrapper script for exa to give it nearly identical switches and appearance to ls. Also automatically adds --git switch when in a git repository.
#!/bin/bash
## Change following to '0' for output to be like ls and '1' for exa features
# Don't list implied . and .. by default with -a
dot=1
# Show human readable file sizes by default
hru=1
# Don't show group column
fgp=0
# Don't show hardlinks column
lnk=0
# Group directories first in long listing by default
gpd=0
# Show file git status automatically (can cause a slight delay in large repo subdirectories)
git=1
help() {
cat << EOF
${0##*/} options:
-a all
-A almost all
-1 one file per line
-x list by lines, not columns
-l long listing format
-G display entries as a grid *
-k bytes
-h human readable file sizes
-F classify
-R recurse
-r reverse
-d don't list directory contents
-D directories only *
-M group directories first *
-I ignore [GLOBS]
-i show inodes
-N no colour *
-S sort by file size
-t sort by modified time
-u sort by accessed time
-U sort by created time *
-X sort by extension
-T tree *
-L level [DEPTH] *
-s file system blocks
-g don't show/show file git status *
-n ignore .gitignore files *
-@ extended attributes and sizes *
* not used in ls
EOF
exit
}
[[ "$*" =~ --help ]] && help
exa_opts=()
while getopts ':aAtuUSI:rkhnsXL:MNg1lFGRdDiTx@' arg; do
case $arg in
a) (( dot == 1 )) && exa_opts+=(-a) || exa_opts+=(-a -a) ;;
A) exa_opts+=(-a) ;;
t) exa_opts+=(-s modified); ((++rev)) ;;
u) exa_opts+=(-us accessed); ((++rev)) ;;
U) exa_opts+=(-Us created); ((++rev)) ;;
S) exa_opts+=(-s size); ((++rev)) ;;
I) exa_opts+=(--ignore-glob="${OPTARG}") ;;
r) ((++rev)) ;;
k) ((--hru)) ;;
h) ((++hru)) ;;
n) exa_opts+=(--git-ignore) ;;
s) exa_opts+=(-S) ;;
X) exa_opts+=(-s extension) ;;
L) exa_opts+=(--level="${OPTARG}") ;;
M) ((++gpd)) ;;
N) ((++nco)) ;;
g) ((++git)) ;;
1|l|F|G|R|d|D|i|T|x|@) exa_opts+=(-"$arg") ;;
:) printf "%s: -%s switch requires a value\n" "${0##*/}" "${OPTARG}" >&2; exit 1
;;
*) printf "Error: %s\n --help for help\n" "${0##*/}" >&2; exit 1
;;
esac
done
shift "$((OPTIND - 1))"
(( rev == 1 )) && exa_opts+=(-r)
(( hru <= 0 )) && exa_opts+=(-B)
(( fgp == 0 )) && exa_opts+=(-g)
(( lnk == 0 )) && exa_opts+=(-H)
(( nco == 1 )) && exa_opts+=(--color=never) || exa_opts+=(--color=always)
(( gpd >= 1 )) && exa_opts+=(--group-directories-first)
(( git == 1 )) && \
[[ $(git -C "${*:-.}" rev-parse --is-inside-work-tree) == true ]] 2>/dev/null && exa_opts+=(--git)
exa --color-scale "${exa_opts[@]}" "$@"
@tachoknight
Copy link

tachoknight commented Apr 6, 2021

Hey, I made a modification to your script to change -h to -H for help; -h shows the size in human readable format (e.g. k for kilobytes). Thanks for writing this, it's really nice!

@tachoknight
Copy link

tachoknight commented Apr 6, 2021

Also, I have too many years of ls to use exa so I compromised and put this script in $HOME/.local/bin renamed this to lls.sh and did a ln -s lls.sh lls and now muscle memory is basically there, I just have to type an additional "l". :)

@eggbean
Copy link
Author

eggbean commented Apr 7, 2021

@tachoknight You can make an alias to replace ls by adding this to your ~/.bash_aliases file (assuming it is called exa-wrapper.sh and you are using bash):

if command -v exa >/dev/null; then
    alias ls='exa-wrapper.sh'
else
    alias ls='/bin/ls $LS_OPTIONS'
fi

@tachoknight
Copy link

tachoknight commented Apr 7, 2021

I considered making an alias but I have a number of jobs that make use of ls output with awk that would break, so I opted to leave ls as-is and go with something only I'd know. I'm also experimenting with ks as it's just one key over from l. Definitely need to work on the muscle memory!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment