Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Until Recently I had alias sudo='sudo ' in my .zshrc file. Today I ran into this error on trying to do sudo mv:

➜  ~  sudo mv nginx.conf.orig nginx.conf.orig2
sudo: nocorrect: command not found

Now googling around I found out that this seemed to be to do with some commands that are prefixed with nocorrect and that I could fix this with alias sudo='nocorrect sudo'.

However the problem comes when I try to set my alias to alias sudo='nocorrect sudo ' to allow myself to use additional aliases. I also ensured that my su was using zsh as mentioned here.

➜  ~  alias sudo='nocorrect sudo '            
➜  ~  sudo mv nginx.conf.orig nginx.conf.orig2
sudo: nocorrect: command not found
➜  ~  alias sudo='nocorrect sudo'                           
➜  ~  sudo mv nginx.conf.orig nginx.conf.orig2
➜  ~  su
Password: 
michaelarch# ps -p $$
  PID TTY          TIME CMD
25831 pts/1    00:00:00 zsh

Does anyone have any suggestions on how to resolve this?

EDIT: alias sudo='sudo ' allows you to use aliases with your sudo commands, for an example see below.

➜  ~  alias cat='echo hello'     
➜  ~  echo goodbye > example.txt
➜  ~  cat example.txt           
hello example.txt
➜  ~  sudo cat example.txt 
goodbye
➜  ~  alias sudo='sudo '
➜  ~  sudo cat example.txt
hello example.txt

For some more info on my shell:

➜  ~  sudo chsh                               
Changing shell for root.
New shell [/usr/bin/zsh]:    
➜  ~  unalias sudo; alias sudo='nocorrect sudo '
➜  ~  echo $SHELL; which sudo                   
/usr/bin/zsh
sudo: aliased to nocorrect sudo 
➜  ~  sudo mv nginx.conf.orig2 nginx.conf.orig  
sudo: nocorrect: command not found
➜  ~  which mv
mv: aliased to nocorrect mv
share|improve this question
1  
What is the purpose of alias sudo='sudo '? –  mpy May 3 at 13:53
    
@mpy it allows you to use other aliased commands with sudo which you can't otherwise do, I'll put an example up. –  Mike H-R May 3 at 13:54
    
I see... I suspect that this is the problem: You define a sudo alias, then a nocorrect sudo alias on top. So finally sudo nocorrect sudo ... will be executed and throws you sudo: nocorrect: command not found as nocorrect is a shell builtin. Try unalias sudo; alias sudo='nocorrect sudo '. –  mpy May 3 at 13:58
    
@mpy good idea. when I read that I thought you were right but trying it unfortunately it didn't work: unalias sudo; alias sudo='nocorrect sudo '; ➜ ~ sudo mv nginx.conf.orig2 nginx.conf.orig sudo: nocorrect: command not found –  Mike H-R May 3 at 14:01
    
What does echo $SHELL; which sudo say? –  mpy May 3 at 14:02

3 Answers 3

up vote 5 down vote accepted

The behavior is reproducible with:

alias sudo='nocorrect sudo '
alias mv='nocorrect mv '

So, when executing sudo mv foo bar this gets expanded to

nocorrect sudo nocorrect mv foo bar

and throws an error as nocorrect is a shell reserved word and cannot be handled by sudo.

The reason that the mv alias gets expanded is that you define alias sudo='nocorrect sudo ' with a trailing blank, which enables alias expansion afterwards. Without that trailing blank this example works, but you loose the capability to use aliases after sudo completely.

A workaround to have alias expansion generally after sudo, but to prevent the error with sudo mv escape the mv command when using it with sudo:

sudo \mv foo bar

This prevents the alias expansion of mv.

share|improve this answer
    
@Mike H-R I'm pretty sure you can solve your issue more elegant, perhaps by defining a zstyle for mv that the correct completer isn't used and you don't need the mv alias. That's only an idea, and I'm no pro at that, so thats why I included no code for that approach. Btw. to just make sure: You need the CORRECT_ALL option to correct all commands _and arguments -- CORRECT for correction of commands only it's sufficient? –  mpy May 3 at 14:47
    
hahaha, I just wrote a giant in depth answer but I like yours better. have a +1 and an accept. –  Mike H-R May 3 at 14:52
1  
+1 but a minor quibble: nocorrect is not a builtin it is a "reserved word" whatever that means (you can check with type nocorrect). –  terdon May 3 at 15:06
    
Thanks, you are absolutely right, corrected the terminology. –  mpy May 3 at 15:08
    
@terdon: Btw, IMHO you can overload a shell builtin with a function, but not a reserved word. –  mpy May 3 at 15:16

Ok, I've been digging into this for a while and have found some stuff on the zsh mailing list. There doesn't seem to be one "silver bullet" solution but a bunch of different solutions which do different things. I'm going to post what I've done (which is a bit of a cop out) but also explore the other approaches and their problems. I'm personally going to go with:

➜  ~  alias sudo='sudo '
➜  ~  alias nsudo='nocorrect sudo'

EDIT:

I am now going to go with

sudo \mv foo bar

for the cases where I need this as descibed by @mpy in the alternate answer.

/EDIT

because it will allow me to use aliases most of the time and when they complain because they're aliased to nocorrect I can use nsudo so that I don't accidentally clobber my files.

Better approaches are from the zsh mailing lists. There appears to be two threads that I've found on this. One from 1999 here (that's the question, see the follow ups, especially this one which solves the noglob problem. I am unsure if it solves nocorrect as well (does noglob imply nocorrect? otherwise I don't think it does, please comment)

alias sudo='my_sudo '

function my_sudo {
    while [[ $# > 0 ]]; do
        case "$1" in
        command) shift ; break ;;
        nocorrect|noglob) shift ;;
        *) break ;;
        esac
    done
    if [[ $# = 0 ]]; then
        command sudo zsh
    else
        noglob command sudo $@
    fi
}

Which satisfies both of my requirements from my question:

➜  ~  alias cat='echo hello'     
➜  ~  echo goodbye > example.txt
➜  ~  sudo cat
hello
➜  ~  sudo mv example.txt2 example.txt

It also seems that this came up again in 2008 on the mailing list with a solution like so:

alias sudo='noglob do_sudo '
function do_sudo
{
    integer glob=1
    local -a run
    run=( command sudo )
    if [[ $# -gt 1 && $1 = -u ]]; then
        run+=($1 $2)
        shift ; shift
    fi
    (($# == 0)) && 1=/bin/zsh
    while (($#)); do
        case "$1" in
        command|exec|-) shift; break ;;
        nocorrect) shift ;;
        noglob) glob=0; shift ;;
        *) break ;;
        esac
    done
    if ((glob)); then
        PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $~==*
    else
        PATH="/sbin:/usr/sbin:/usr/local/sbin:$PATH" $run $==*
    fi
}

Which seems to be doing a lot that I admittedly don't fully understand. This seems to ignore autocorrect (as stated by the author).

share|improve this answer
    
Yes, the zsh mailing list is a huge source for high-quality solutions -- and I appreciate your efforts to write such an elaborate answer. +1 :) –  mpy May 3 at 15:05

The problem, as I explain in my answer here, is that sudo starts a separate shell. On most, if not all, Linux distributions, the default shell is bash and not zsh. Since nocorrect is a zsh builtin, it is not available in bash and so you get the command not found error.

The solution is to set sudo to sue zsh as well:

sudo chsh

Then set it to /usr/bin/zsh. That should make sudo start a zsh shell and your alias will work as expected.

share|improve this answer
    
Thanks terdon, but as I explained I'm already running zsh (see after the su command.) –  Mike H-R May 3 at 14:04
    
You have a point, but I don't understand it: sudo mv ... should expand to nocorrect sudo mv ..., so no nocorrect in the argument of sudo?! –  mpy May 3 at 14:05
    
@mpy just added something that might explain, mv is aliased to nocorrect mv –  Mike H-R May 3 at 14:07
    
@MikeH-R and I just realized you've already set the sudo shell to zsh. Try this instead: alias sudo='nocorrect /usr/bin/sudo'. I'm not sure but I think the issue might be that the alias is calling itself. If so, that should fix it. Let me know and I'll edit my answer. –  terdon May 3 at 14:08
    
@mpy you're quite right. I think I missed the point entirely, see my comment to the OP above. –  terdon May 3 at 14:09

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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