Lazy Aliases & Bash Gibberish

I really do love aliases. I mean:

Off late I've been using docker a lot, and I find myself running these two commands often:

docker ps -a
To list all docker containers (running or stopped)
docker exec -it <container name> <cmd>
And to run a command on a container - most likely running bash to get shell access

Now that's a lot of characters - and I also really hate having to hit the spacebar - introduces even more scope for typos.

So I wanted to alias them to dps and dsh respectively.

The first one is straight forward. It can even just be a shell alias like alias dps='docker ps -a', but generally I prefer to keep them as tiny utilities in my ~/bin folder.


docker ps -a

As for dsh, this one has some dynamic-ness to it. So here's the spec:

  1. Ability to specify the container name or ID
  2. Ability to specify command to run, but default to running bash since that is the most common use case.

Here's the 5-second solution:
(i.e. compromise by skipping half the spec)


docker exec -it $1 $2

This works to some extent - the first argument is the tag, and the second is the command, but it doesn't gracefully fallback to using bash as the default. Also, this only works for one-word commands as arguments since we are using $2 and not $@ - but that is easily fixed even in the 5-second solution.

Now we could assign cmd=bash and then with check if $2 exists in an if condition and overwrite $cmd, but I wanted to find a one-liner akin to the logical OR operator that we have in JavaScript like const cmd = ARGV[1] || "bash" .

Enter Shell Parameter Expansion
(a.k.a the 20mins + write a blog post time solution)

Yeah that's a mouthful. As with most things to do with shell scripting - we're about to type a bunch of gibberish.

Turns out the shell equivalent of the JavaScript logical OR operator looks like this:


If parameter is unset or null, the expansion of word is substituted. Otherwise, the value of parameter is substituted[1].

With some experimenting, I found that this works just fine:


# First argument is always the tag

# throw away the first argument

# Save the rest of the arguments as the command to execute,
# but if they don't exist assign string 'bash' to cmd

docker exec -it $tag $cmd

I'm often using it like:

❯ dsh web
# => Enter bash shell at container web

❯ dsh alpine1 ash
# => Enter ash shell at container alpine1

❯ dsh alpine1 ping -c 1
PING ( 56 data bytes
64 bytes from seq=0 ttl=37 time=11.380 ms

--- ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 11.380/11.380/11.380 ms

You can find my repository of tiny bin utilities over at

  1. Source: