Difficulty: ★★★☆☆
DISCLAIMER
The shell code below is to be added to one’s
~/.bashrc
file and is only guaranteed to work with GNUbash
. I do not use and have no experience withzsh
.
Many people ─ especially the resident newbies ─ prefer zsh
as an interactive shell because of the fact that it is highly themeable. Yet, at the basis, like most distributions, Manjaro still uses bash
for its system initialization scripts, because bash
is very powerful and it has stood the test of time as a reliable shell.
Nowadays, zsh
is the Manjaro default interactive shell for new installations ─ even if only for its visual appeal ─ but back when I first installed Manjaro now about two and a half years ago (at the time of my writing this), bash
was still the default interactive shell for unprivileged user accounts, and as a 20-plus-year GNU/Linux veteran, I saw no need to change that.
Therefore, as the disclaimer says, if you are using zsh
, then the following code may not be of interest to you. But if you do still use bash
and you find this code interesting, then feel free to implement it, modify it, or whatever. It’s all GPL, homie!
The default ~/.bashrc
that ships with Manjaro already contains some aliases and functions ─ probably literally taken over from Arch, but if I’m wrong about that, then feel free to correct me ─ but I have added a couple more of my own, based upon the needs of the moment. I will give a brief description with each of them below.
Perhaps first a word about the difference between aliases and shell functions.
An alias is in fact only a shorthand for simple commands that you use a lot but would take too much time to type in every time. An alias can be a compound command ─ it can be made up of multiple existing commands ─ but it cannot be used for the manipulation of variables.
An alias always comes in the form…
alias name-of-your-alias-here='command(s)-to-be-executed'
A shell function on the other hand is much more powerful. It is very much like a shell script that you store in a separate file ─ and come to think of it, you can actually do that with functions as well if you source the file that contains the function(s) from within your ~/.bashrc
─ but there are two main differences…:
- A shell script is always executed in a subshell, not in the running shell.
- A shell script is executed from an external file, which first needs to be opened and read into memory.
If on the other hand you include the code in your ~/.bashrc
, then whenever you open a terminal window or log in at a tty
, the code will already be in memory and can be executed right away, just as if it were an internal command of the bash
executable itself.
Like I said, Manjaro already ships a ~/.bashrc
with some aliases and functions in it by default, and there are also yet other places where shell configuration takes place, both system-wide and in your own user account ─ e.g. ~/.bash_profile
and/or ~/.profile
. So I’m only going to be posting some things that I myself have added to my ~/.bashrc
for my convenience.
Here goes…
This here is an alias that Plasma users will probably find useful. It restarts the compositor, which you may have already been needing to do in the last two or three Plasma releases because of the bug that leaves ghost images in the compositor’s memory buffer.
alias restart-compositor='qdbus org.kde.KWin /Compositor suspend && qdbus org.kde.KWin /Compositor resume'
The following two are also useful for Plasma users, because it allows you to lock your widgets or unlock them again from the command line.
alias widgets-lock='qdbus org.kde.plasmashell /PlasmaShell evaluateScript "lockCorona(true)"'
alias widgets-unlock='qdbus org.kde.plasmashell /PlasmaShell evaluateScript "lockCorona(false)"'
As you can see, it’s a lot easier to type the name of the aliases than to type the full qdbus
commands.
As for the functions, you can invoke a function by simply typing its name as a command at the prompt, just as you do with an alias.
The first function below modifies the man
command so that man
pages can be viewed in color.
man ()
{
LESS_TERMCAP_md=$'\e[01;37m' \
LESS_TERMCAP_me=$'\e[0m' \
LESS_TERMCAP_so=$'\e[01;44;32m' \
LESS_TERMCAP_se=$'\e[0m' \
LESS_TERMCAP_us=$'\e[01;33m' \
LESS_TERMCAP_ue=$'\e[0m' \
command man "$@"
}
export -f man
I have created and refined the following two shell functions in the last couple of days, and they have been properly tested. They work as regular shell commands, and they take a directory name ─ even one that contains spaces, if you properly escape them or use quotes around the name ─ as an argument.
If you do not supply any command-line argument, then they will be executed in the current working directory ─ they do not descend into subdirectories below the current or specified directory. They both also ask for confirmation before doing their stuff so that you can abort the operation if you’re not sure, and they both also provide for an exit code ─ 0
for success (even if you abort the operation) and 1
for incorrect usage.
The purpose of these two functions is to translate spaces in filenames into underscores, and vice versa. The name of either function should make it clear enough which is which.
spaces2underscores ()
{
targetdir="$*"
if [ ! -z "$1" ]
then
if [ -d "${targetdir}" ]
then
oldpwd=$(pwd)
else
echo "Not a valid directory."
return 1
fi
fi
read -n1 -p "Rename all files in ${targetdir}? [y/N]"
case ${REPLY} in
"Y" | "y" )
cd "${targetdir}"
fncounter=0
for fn in *
do
newfn=$(printf "${fn}" | tr ' ' '_')
if [ "${newfn}" != "${fn}" ]
then
mv "${fn}" "${newfn}"
fncounter=$((${fncounter}+1))
fi
done
cd "${oldpwd}"
echo "Successfully replaced spaces by underscores in ${fncounter} filename(s)."
echo
;;
* )
echo "Operation aborted."
echo
return 0
;;
esac
unset targetdir oldpwd REPLY fncounter fn newfn
}
underscores2spaces ()
{
targetdir="$*"
if [ ! -z "$1" ]
then
if [ -d "${targetdir}" ]
then
oldpwd=$(pwd)
else
echo "Not a valid directory."
return 1
fi
fi
read -n1 -p "Rename all files in ${targetdir}? [y/N]"
case ${REPLY} in
"Y" | "y" )
cd "${targetdir}"
fncounter=0
for fn in *
do
newfn=$(printf "${fn}" | tr '_' ' ')
if [ "${newfn}" != "${fn}" ]
then
mv "${fn}" "${newfn}"
fncounter=$((${fncounter}+1))
fi
done
cd "${oldpwd}"
echo "Successfully replaced underscores by spaces in ${fncounter} filename(s)."
echo
;;
* )
echo "Operation aborted."
echo
return 0
;;
esac
unset targetdir oldpwd REPLY fncounter fn newfn
}
export -f spaces2underscores underscores2spaces
As you can see, I have put an export -f
command underneath each code block. This command is not part of the functions themselves, but instead, it makes sure that the functions are exported into any subshells that may get started, just as you can export variables.
You also don’t need to write an export -f
command for each of the code blocks. You can define all of your functions and then simply put a single export -f
line at the bottom that exports all of the functions in one go, like so…
export -f this-function-here that-function-there another-function-here ...
I hope this was useful, and as always, I am looking forward to hearing your expert opinions in the comment section below. Please like and subscribe, hit that notification bell, and don’t forget to share with all your friends on FaceTube.