Aliases, whether you use Bash, ZSH or any other shell, are a really easy way to improve your day to day workflow. The basic syntax for aliases is the following:
alias l='ls -al'
This syntax is pretty simple, but is unfortunately very limited in what you can do:
- it doesn't let you handle custom parameters. What if you want to add a custom
--jsonparameter tocurlthat expands to--header "Content-Type: application/json"? - it doesn't let you add subcommands. What if you want to create a custom
docker shsubcommand that expands todocker exec -it container_name sh?
Well the cool thing is that you can do all of that, simply using shell functions! Yep, nothing new in here, but using functions to create advanced aliases is often disregarded or forgotten.
Anyway, let's see how to implement the above aliases!
Note: The following snippets will use Bash specifically. It should not be too hard to adapt them to other shells.
Add a custom flag to a command
When using curl, I often want to send JSON payloads. To do so, the Content-Type: application/json header is usually required by servers. I'd like to be able to write this:
curl --json -d '{"foo": "bar"}' https://example.com/endpoint
instead of this:
curl -H 'Content-Type: application/json' -d '{"foo": "bar"}' https://example.com/endpoint
You can add this custom flag with the following function:
curl() {
local -a args;
for arg in "$@"; do
case $arg in
--json) args+=("-H" "Content-Type: application/json") ;;
*) args+=("$arg") ;;
esac
done
command curl "${args[@]}"
}
So what happens in this snippet?
- At first, we create a new
curlfunction. It will wrap the already existingcurlcommand and we'll be able to modify how it's called. - Then, we loop on all the arguments passed to the command, and add them to a new
argsarray. - When we encounter the
--jsonargument, we push the new arguments"-H" "Content-Type: application/json"to our list instead. - Finally, we call the original
curlcommand with the modified list of arguments. Make sure to usecommandin front ofcurlto avoid calling the alias function recursively.
And that's it! There's no magic in here, we just cleverly use some basic Bash building blocks.
Using the same techniques, we can easily decide to replace the -d argument with --json to get the following final command:
curl --json '{"foo": "bar"}' https://example.com/endpoint
This is left as an exercise to the reader.
Add a custom subcommand to a command
When using docker, it's common to get into a container to explore the file hierarchy. The command to do this operation is the following:
docker exec -it container_name sh
I want to write this instead:
docker sh container_name
The principle is the same as above, you can write a function like this:
docker() {
if [ $# -ge 1 ]; then
case "$1" in
"sh")
if [ $# -ne 2 ]; then
echo '"docker sh" requires 1 argument.'
echo
echo "Usage: docker sh NAME|ID"
echo
echo "Start an interactive shell inside a running container"
return 1
fi
command docker exec -it "$2" bash
;;
esac
fi
command docker "$@"
}
The only difference with the previous script is that we create a new sh subcommand that we implement ourselves.
We could trivially implement additional flags (--help, --bash, etc.) to our new subcommand following the same patterns.
This article contains no novel concepts, but will helpfully help you get creative in creating more specific aliases to your workflows.
The main thing to remember is the existence of the command built-in that allows you to declare a function with the same name as an existing command, and still be able to use the original command.
Top comments (0)