DEV Community

Thibaut Rousseau
Thibaut Rousseau

Posted on

Shell aliases on steroids

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'
Enter fullscreen mode Exit fullscreen mode

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 --json parameter to curl that expands to --header "Content-Type: application/json"?
  • it doesn't let you add subcommands. What if you want to create a custom docker sh subcommand that expands to docker 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
Enter fullscreen mode Exit fullscreen mode

instead of this:

curl -H 'Content-Type: application/json' -d '{"foo": "bar"}' https://example.com/endpoint
Enter fullscreen mode Exit fullscreen mode

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[@]}"
}
Enter fullscreen mode Exit fullscreen mode

So what happens in this snippet?

  • At first, we create a new curl function. It will wrap the already existing curl command 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 args array.
  • When we encounter the --json argument, we push the new arguments "-H" "Content-Type: application/json" to our list instead.
  • Finally, we call the original curl command with the modified list of arguments. Make sure to use command in front of curl to 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

I want to write this instead:

docker sh container_name
Enter fullscreen mode Exit fullscreen mode

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 "$@"
}
Enter fullscreen mode Exit fullscreen mode

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.

Discussion (0)