I get a lot of questions on why I use a shell as opposed to a GUI for things. A
shell is often annoying to do some basic things even if it's much more powerful
and generally a tradeoff. Deleting all files ending in .txt
is hard in a gui,
but in a shell is just rm *.txt
. Meanwhile, going up a directory in a gui is
easy. Just hid the back button on the mouse. In a shell it's cd ..
which is a
lot to type for something so simple. Another common issue that I had was
different operating systems or even Linux distros having different commands to
do basically the same thing. On Debian it's sudo apt install <package>
and Mac
it's brew install <package>
. This gets quite annoying to have to remember what
system you are on, and understand the differences in them.
All of the above complaints can go away. Changing directories can be shortened.
# Changing dirs with just dots.
alias .='cd ../'
alias ..='cd ../../'
alias ...='cd ../../../'
alias ....='cd ../../../../'
This is just one example. Maybe you want to have commands that work on both Mac
and Linux. What if it even matters if you are running Wayland or X11? Still can
be easily solved.
if command -v pbcopy > /dev/null 2>&1; then
alias xclip='pbcopy'
elif command -v wl-copy > /dev/null 2>&1; then
alias xclip='tee >(wl-copy) | wl-copy -p'
fi
The above makes xclip
be the actual xclip
if there are no better options, or
sets it to the Mac or Wayland version if those exist instead. No need to
remember what system you are on, or what software stack. It automatically adapts.
I'll mostly let the code speak for itself as it's easy to understand, but this
makes traveling between machines nearly seamless as there is nothing new to
learn or remember.
if command -v xbps-install > /dev/null 2>&1; then
export IS_VOID=1
elif command -v emerge > /dev/null 2>&1; then
export IS_GENTO=1
elif command -v pacman > /dev/null 2>&1; then
export IS_ARCH=1
elif command -v apt-get > /dev/null 2>&1; then
export IS_DEBIAN=1
elif command -v apk > /dev/null 2>&1; then
export IS_ALPINE=1
elif [[ "$OSTYPE" == "darwin"* ]]; then
export IS_MAC=1
else;
export IS_BSD=1
fi
if [ "${IS_ARCH}" = "1" ]; then
## Package Manager - pacman/yay
if command -v yay > /dev/null 2>&1; then
alias pi='yay -S'
alias pr='yay -R'
alias psearch='yay -Slq | fzf --multi --preview 'yay -Si {1}' | xargs -ro yay -S'
alias pu='yay -Syu --devel --timeupdate'
alias oneshot='yay -S --asdeps'
alias orphans="yay -Qtdq | yay -Rns -"
else;
alias pi='sudo pacman -S'
alias pr='sudo pacman -R'
alias psearch='pacman -Slq | fzf --multi --preview 'sudo pacman -Si {1}' | xargs -ro sudo pacman -S'
alias pu='sudo pacman -Syu'
alias oneshot='sudo pacman -S --asdeps'
alias orphans="pacman -Qtdq | sudo pacman -Rns -"
fi
alias mirrorupdate="sudo pacman-mirrors --geoip && sudo pacman -Syyu"
alias etc-update="sudo pacdiff"
alias asdep="sudo pacman -D --asdeps"
alias explicit="sudo pacman -D --asexplicit"
elif [ "${IS_DEBIAN}" = "1" ]; then
## Package Manager - apt
alias pi='sudo apt install'
alias pr='sudo apt remove'
alias psearch='apt search'
alias pu='sudo apt update && sudo apt upgrade'
alias orphans='apt autoremove'
elif [ "${IS_GENTOO}" = "1" ]; then
## Package Manager - portage/emerge
alias gsync='sudo eix-sync'
alias pi='sudo emerge -av --autounmask'
alias oneshot='sudo emerge -av --oneshot'
alias pu='sudo emerge --update --deep --with-bdeps=y --newuse --keep-going @world --ask'
alias pub='sudo emerge --update --deep --with-bdeps=y --newuse --keep-going @world --ask --binpkg-changed-deps'
alias pr='sudo emerge --depclean -av'
alias psearch='eix -r'
alias pclean='sudo qpkg -c'
alias howlong='sudo watch --color genlop -uic'
alias etcupdate='sudo -E etc-update --automode -3'
elif [ "${IS_ALPINE}" = "1" ]; then
## Package Manager - apk
alias pi='sudo apk add'
alias pr='sudo apk del'
alias psearch='sudo apk search'
alias pu='sudo apk update && sudo apk upgrade'
elif [ "${IS_VOID}" = "1" ]; then
## Package Manager - void/xpbs
alias pi='sudo xbps-install -S'
alias prr='sudo xbps-remove -R'
alias pr='sudo xbps-remove'
alias psearch='sudo xbps-query -Rs'
alias pu='sudo xbps-install -Su'
alias orphans='sudo xpbs-remove -o'
elif [ "${IS_MAC}" = "1" ]; then
## Package Manager - brew
function pi {
brew install "${@:1}"
brew bundle dump --force --file=$HOMEBREW_BREWFILE
}
function pic {
brew install cask "${@:1}"
brew bundle dump --force --file=$HOMEBREW_BREWFILE
}
function pr {
brew uninstall cask "${@:1}"
brew bundle dump --force --file=$HOMEBREW_BREWFILE
}
alias psearch='brew search'
alias pu='brew update && brew upgrade'
alias orphans='brew autoremove'
elif [ "${IS_BSD}" = 1 ]; then
## Package Manager - freebsd
alias pi='sudo pkg install'
alias pr='sudo pkg remove'
alias psearch='sudo pkg search'
alias pu='sudo pkg update && sudo pkg upgrade'
fi
There is a combination of aliases and functions used in there. Aliases are
simple commands, functions can have more advanced actions attached, but both act
as a "normal" command as far as a user sees.
A lot of the time you want to do the same thing. When you want to rm
files,
most of the time you probably want to remove a directory recursively, as opposed
to deleting everything inside, and using rmdir
. You can alias over commands
and add default arguements.
# Default flags
alias cp='cp -R -i -v'
alias mv='mv -i -v'
alias mkdir='mkdir -p -v'
alias df='df -h'
alias du='du -h -s'
alias dd='dd status=progress bs=4M conv=fdatasync '
alias wgetpaste='wgetpaste -Xx'
alias sudo='sudo ' # Makes sudo work with aliases
alias ssh='TERM=xterm ssh' # Fixes some issues with ssh on some terminals
I mentioned that functions can do a bit more than a basic alias. Here's a few
more examples of that in action.
# Easy extract
extract () {
if [ -f $1 ] ; then
case $1 in
*.tar.bz2) tar xvjf $1 ;;
*.tar.gz) tar xvzf $1 ;;
*.tar.xz) tar xvJf $1 ;;
*.bz2) bunzip2 $1 ;;
*.rar) unrar x $1 ;;
*.gz) gunzip $1 ;;
*.tar) tar xvf $1 ;;
*.tbz2) tar xvjf $1 ;;
*.tgz) tar xvzf $1 ;;
*.txz) tar xvJf $1 ;;
*.rar) unrar $1 ;;
*.zip) unzip $1 ;;
*.Z) uncompress $1 ;;
*.7z) 7z x $1 ;;
*) echo "don't know how to extract '$1'..." ;;
esac
else
echo "'$1' is not a valid file!"
fi
}
# Makes directory then moves into it
function mkcdr {
mkdir -p -v $1
cd $1
}
# Creates an archive from given directory
mktar() { tar cvf "${1%%/}.tar" "${1%%/}/"; }
mktgz() { tar cvzf "${1%%/}.tar.gz" "${1%%/}/"; }
mktbz() { tar cvjf "${1%%/}.tar.bz2" "${1%%/}/"; }
mkzip() { 7z a -r "${1%%/}.zip" "${1%%/}/"; }
mk7zip() { 7z a -r "${1%%/}.7z" "${1%%/}/"; }
I know this was a short post that was heavy in raw text from files, but it's
meant to highlight some of my dotfiles that make my life much easier, and I think
would be useful to many others. Even if you don't use the exact lines, you can
see how things are used, get new ideas, and maybe make something even better for
your workflow than you could just grab from using my files blindly. I didn't go
deeply into things that bash can't do that ZSH can, but I may do a more in depth
dive of my .zshrc
to pull out some of those things at a later date. These are
only snippits of my dotfiles. They can all be found, in full
here for further reading and
extraction. ZSH related files are .zshrc .zshenv .zsh_aliases
as I have split
my zsh for easier reading and editing.
Here are the aliases I use to open my zsh files for editing.
alias zshrc="$EDITOR ~/.zshrc"
alias zshenv="$EDITOR ~/.zshenv"
alias zshaliases="$EDITOR ~/.zsh_aliases"