Creating an alias containing bash history expansion

7

2

I often forget to run a command with sudo, so I find myself often typing sudo !! immediately afterwards.

I tried aliasing this, but bash chokes on the !! part. Is there some way to represent this shortcut within an alias?

andrewdotnich

Posted 2011-02-01T00:41:32.167

Reputation: 245

That's not a wild-card that's a history expansion feature. History expansion is performed before alias expansion so when the alias is expanded the !! are considered literal. – Paused until further notice. – 2011-02-01T01:54:58.793

Answers

10

AIUI the problem is that history substitutions (!!) are done before alias substitution. I haven't tested this thoroughly, but it looks like fc can be used to get what you want:

alias sudothat='eval "sudo $(fc -ln -1)"'

Gordon Davisson

Posted 2011-02-01T00:41:32.167

Reputation: 28 538

1No need for the eval (plus it may have some undesirable effects). – Paused until further notice. – 2011-02-01T01:38:22.203

Without the eval, it won't parse things like the quoted strings correctly, and with double-quotes around the results of fc it should evaluate everything exactly once -- which is what you want. – Gordon Davisson – 2011-02-01T03:47:31.967

@Dennis Williamson: I've now tested this a bit more thoroughly, and it seems to work as expected (i.e. the same as typing sudo !!) for everything I've tried -- quoted arguments, pipelines, command substitutions, command substitutions containing command substitutions containing pipes... I don't see any way to do this right without an eval. – Gordon Davisson – 2011-02-19T15:45:24.023

5

From a colleague at work:

alias sa='sudo `history -p \!\!`'

appears to do the trick

andrewdotnich

Posted 2011-02-01T00:41:32.167

Reputation: 245

1it should be noted that this only works when using single quotes ('). – Torian – 2011-02-01T03:42:30.990

This won't handle quoted arguments properly -- for example, if you use it to rerun echo "a   b" (which prints a   b), it'll print "a b" (as in, the quotes are actually included in the arguments passed to echo, but the spaces between aren't). – Gordon Davisson – 2011-02-01T03:50:43.197