I'm trying to override docker ps to be docker ps --format="table {{.ID}} {{.Image}} {{.Status}}"

I've read this SO question and the referenced documentation, but I can't get it to work.

I've tried a few things that "compile", here's the latest attempt.

alias func='dockerps'

function dockerps() {
 'docker ps'='docker ps --format="table {{.ID}} {{.Image}} {{.Status}}"'$\

How can I fix my code such that typing docker ps will preserve my formatting?


There is no such thing as a multi-word alias. The SO answer you refer to seems plain mistaken to me: it doesn't make any sense, and I can't find any trace of any feature that would yield anything close to the desired effect, even when digging through the zsh history to look for a possible experimental feature in 4.3 (the development version of zsh at the time) that would have been removed before the 5.0 release. What you wrote has a well-defined meaning: it defines an alias for func and a function called dockerps, so it only has an effect on command line where the first word is func or dockerps. If the function is ever invoked, it attempts to set a variable with an invalid name, which fails.

Zsh lets you can define an alias for a word that includes special characters, for example

darkstar% alias "'docker ps'"='echo docker ps in single quotes'
darkstar% alias 'docker\ ps'='echo docker backslash ps'                 
darkstar% 'docker ps'
docker ps in single quotes
darkstar% docker\ ps
docker backslash ps
darkstar% "docker ps"
zsh: command not found: docker ps

But this is not particularly useful. 'docker ps' is one word but docker ps is two words.

You'll have to do it the normal way: define a function called docker, and have it analyze its argument. Here's a simple version that supports global options, but requires using --option=value rather than --option value for global options that take an argument.

docker () {
  setopt local_options extended_glob unset
  local -i i=$argv[(i)^-*]
  # $argv[i] is the first non-option argument (or empty if there is none).
  # See if we want to insert something after it.
  case $argv[i] in
    ps) argv[i+1,i]=(--format="table {{.ID}} {{.Image}} {{.Status}}");;
  command docker "$@"
  • It's called out in the README for 5.4.2. It didn't do what people thought that it did in any event.
    – JdeBP
    Sep 5 '20 at 0:15
  • @JdeBP What are you referring to? I don't see anything that would have allowed multi-word aliases, or that would have made 'docker ps'=… not be an error, or that would have made the code shown in the question have any effect on a command starting with docker ps. Sep 5 '20 at 9:20
  • The README for the Z shell, under the heading "Incompatibilities between 5.3.1 and 5.4.2", item #1. And as I said, the code referenced by the question (and your answer) in the Stack Overflow answer didn't do what people thought that it did in any event.
    – JdeBP
    Sep 5 '20 at 9:44
  • @JdeBP That was about defining (or attempting to define) an alias and a function with the same name, which isn't what that SO answer does. It's also the wrong time frame for that SO answer. Sep 5 '20 at 11:55
  • On the contrary, it's exactly what the answer does. They're both named func, or rather apparently so. The README explains what really used to happen, before 5.4.2.
    – JdeBP
    Sep 6 '20 at 3:13

Technically, like in csh where that alias misfeature comes from, you could do:

alias docker='docker '
alias     ps='ps --format="table {{.ID}} {{.Image}} {{.Status}}"'

Which would achieve what you want but that would mean that:

  1. All words following docker would be subject to alias expansion (that alias cmd='cmd ' trick is intended for commands like command, env, sudo that take commands as arguments so aliases are also expanded after them).
  2. A ps word without docker before it would also be expanded, which means you couldn't run the standalone ps command anymore unless you change the wording of the invocation (like "ps" -ef).

Here, I'd just define a new command with a different name, so it doesn't clash with the original that does what you want:

my-docker-ps() docker ps --format="table {{.ID}} {{.Image}} {{.Status}}" "$@"

Here implemented as a function, though you may prefer to implement it as a script instead so it's also available outside of your shell.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.