Hacker News new | past | comments | ask | show | jobs | submit login
Run last command as root (hardikr.com)
55 points by kingsidharth on Dec 16, 2010 | hide | past | favorite | 59 comments



Hi HN! I'm the post author, and if I would've known someone was submitting this to HN, I would've researched a bit more! This was more for my reference. Thanks for all the tips though, got to learn a lot from this thread..


Something else really useful: mkdir stuff cd !$

!$ takes the last argument from the previous command, instead of the whole thing.

chmod 664 site/* - changes the permissions for all the files in the site directory. * is a wildcard in bash for specifying directories.

Another useful feature of bash is brace expansion: mv site{,-old} => mv site site-old The brace expansion expands the argument with the values in a comma separated list: college pic_00{1,4,3}.jpeg college.jpeg yields pic_001 pic_004, pic_003


* is a wildcard for everything in the directory including files and directories. so the chmod will remove the execute permission from directories also.


* will not match hidden files:

  > ls -a tmp
    file1
    file2
    .file3
  > ls tmp/*
    file1
    file2
  > ls tmp/.*
    .file3


<ALT>-. does the same thing except it prints it before you hit enter.


or <ESC>-. if you recently got a macbook and can't figure out how to remap the silly keyboard defaults and make alt work properly in a terminal..


I have a function for it which is quite useful: mcd () { mkdir "$@" cd "$@" }

Just run mcd foobar and you (try) to create the directory and enter it. IMO a nice shortcut.


You know that mkdir can take multiple directories? If you run:

  mcd dir1 dir2 dir3
That function will run:

  mkdir "dir1" "dir2" "dir3" cd "dir1" "dir2" "dir3"
(Surrounding $@ with double quotes, puts quotes around each item instead of quotes around the whole string:

  command "directory1/sub directory" "directory2"

    $@ => directory1/sub directory directory2
  "$@" => "directory1/sub directory" "directory2"
  "$*" => "directory1/sub directory directory2"

)


* is a wildcard in general. Its behavior is identical to the .* in a regular expression.


The biggest shell-related revelation for me recently was that ~ is a special character in SSH. If you have an SSH session that's hanging and ctrl-C / ctrl-D isn't responding, try typing "~." (without the quotes).

  man ssh | grep -A 30 tilde


The ~ needs to follow a newline. So I usually make sure to hit <Enter> explicitly before hitting "~." so that I don't have to repeat the sequence if it doesn't work. It would still work without hitting <Enter> explicitly if the last thing that you typed to the console was <Enter> though.


If you have an SSH session that's hanging

It's usually because I've accidentally fumbled ctrl-s which means 'play dead'. Why that's important enough to take a two-key home row shortcut, I don't know. The cure is to press ctrl-q. Same wonder about the cure.


I can't argue for it taking such a prime spot on the keyboard, but I used c-s/c-q every day to freeze scrolling output that I want to look at. Your terminal scrollback will still work during the pause.


I prefer Ctrl-P, Ctrl-A, "sudo ", enter

It's pretty much the same number of keystrokes aside from having to hold down the Ctrl key. However, I can now go back in my history and run the command again. Also, if I mistyped something, I can easily hit Ctrl-P and fix it without having to retype sudo.


!! (bang-bang) is expanded by the shell before its committed to your history (at least in bash), so if you hit ctrl+p, you'll get the full sudo command for running/modifying later.


In zsh, !! is expanded by the shell, but leaves the expanded command at the terminal, waiting for you to execute it. Most of the time this means I have to hit enter twice to run the command, but it's convenient when I want to explain to someone what !! is useful for.


I don't have that enabled but zsh also expands bang constructs with tab. So any commands I want to double check, or if I am demonstrating to someone, I just hit tab. Also handy for expressions like !-2:3 where if I messed up I can just hit "undo" and then retry.


Ah. Good to know.


I've always pronounced this command as

"sudo make me a sandwich"


Seriously, though, "!!" is just a special case of Bash's history expansion

man bash, and search for "^HISTORY EXPANSION" for all the details.

I often find myself running commands like

cp !:2 !:1 # reverses the order of the last two args

cd /somedir && !! # run the last command in a better directory


Similarly, I always rehearse dangerous removals with ls :

    ls ./t*
    # looks good...
    rm !$


On a related note, when you want to insert something at the start of a line in a shell, rather than hitting home, I find ctrl-a to be very useful. Especially on a macbook, where cmd-left doesn't work in a shell (for some reason) and there is no home key.

This often works in unexpected places. For example: testing it right now, I can click the address bar on google chrome, hit ctrl-a (not cmd-a) and the caret is at the start of the url.


ctrl-a (beginning of line), ctrl-e (end of line), ctrl-k (kill/copy line), ctrl-y (yank/paste line) are standard emacs keybindings. On OS X, they work in any standard NS text field as well. More at http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html

BTW, when using screen, ctrl-a is its default action key, so use ctrl-a ctrl-a to send a real ctrl-a, or change the default screen action key in your .screenrc.


> BTW, when using screen, ctrl-a is its default action key

This ends up annoying me on a regular basis. Let's say I want to make a directory and then go to it. I would type:

  mkdir foo<Ctrl-p><Ctrl-a><Alt-d>cd<Enter>
Except when using screen, <Ctrl-a><Alt-d> (really just <Ctrl-a>d) detaches the session. It's solved easily enough ("screen -r"), but it always yanks me out of my groove.


Put something like this in your .screenrc:

   escape "^^^^"
That will set the escape character to ctrl-carat instead of ctrl-a. To type a literal ctrl-carat, type it twice.

This is the same as:

   screen -e ^^^^


I prefer to bind it to ` with `` to send a real `. It makes it really easy to flip back and forth between two screen windows since last-window is now:

  `q
Now I don't even have to use Ctrl. This takes a little getting used to, but I prefer to use $() instead of `` for shell scripts (I use bash/zsh) so I don't make use of ` that often.

I do have bindings on F11 and F12 to toggle the escape character between ` and C-o. (Just in case I need to paste something into a terminal with ` characters.)

(Note: This whole setup is ripped off from some StackOverflow or HN post.)


Ctrl-a ctrl-a toggles between screens; ctrl-a a sends a ctrl-a sequence to the terminal.


Another one to add to the list, when working in the shell, is ctrl-u. This sort of does the opposite of ctrl-k and clears everything from your cursor to the start of the line. I use it when I recursive-search then change my mind, or when I screw up a password when ssh'ing.


It's my understanding that these keycombo's are originally from the readline library. Other programs that have these combo's available are irrsi and bash but I love to know more!


Your MacBook does have a home key, it's just not labelled any more. fn+left arrow is home, and end is the obvious counterpart. fn+up/down are page up/down too.

I use ctrl-a and ctrl-e too, but sometimes you're using remote desktop (or synergy) with a Windows machine...


Thanks (to jrockway too), that's something new I learned today!


One of my favorite, under-known Bash tricks: Ctrl-O. "Enter current command, put next history item on command line."

It works like this: You're doing 3 things over and over again, but you need to see each step finished before you want to go on. Something like:

>wget buildserver/artifact.jar >java -j artifact.jar > result.txt >grep "Stupid bug" result.txt >vi config.xml >git commit -a; git push

Something like that. Having done it once, up-arrow into your history to the wget, hit "Ctrl-O" and it'll execute the wget, and now the java command is ready. You can just keep cycling through with Ctrl-O, since executing the command puts it in the end of your history. If you need to update the command, the fix is available for later. One of those "use it so that you remember, 'cause boy-howdy it's handy"


Have a look at zsh, you can execute your current command as root quite easy. Put

  sudo-command-line() {
      [[ -z $BUFFER ]] && zle up-history
      [[ $BUFFER != sudo\ * ]] && BUFFER="sudo $BUFFER"
  }   
  zle -N sudo-command-line
  bindkey "^Os" sudo-command-line
into your zshrc, enter the command and press ctrl+o s et voila ;0

For more cool stuff regarding zsh have a look at http://grml.org/zsh/ or for other nice keybindings http://grml.org/zsh/grmlzshrc.html


zle = zsh line editor

(I doesn't use read-line it has it's own line editor)


I got this from a former co-worker and am now completely reliant:

  alias r='sudo '
Note the space after sudo in the quotes. Cuts down on keystrokes when you have to spend a lot of time sudo-ing.


The space isn't required with Bash :)


I never do this, I prefer to recall the actual command to see if it is correct, especially for sudo.

The reason is that you might not execute the command you were thinking of. The HISTIGNORE variable contains a quasi-regex of commands that are not stored in history. If the previous command matched that regex, you will end up executing the previous command to that one, not what you wanted at all.

Why use HISTIGNORE?. So that things like 'exit' or common commands like 'ls' don't pollute your history file.


I've really enjoyed Ctrl+a and Ctrl+e recently to move between the beginning and end of the command prompt - it's really a lot more useful than I initially thought.


I am just curious, what determines the front page of Hacker News? Because this post has 17 points and the one below it has 130 at this time


Here's an excellent, detailed, and fairly recent explanation of the Hacker News ranking algorithm:

http://amix.dk/blog/post/19574


From what I've seen (and I may be wrong here), I think the post that enters the front page stays on the top just for a short amount of time, before gradually settling down on a position determined by the time it's been there, the votes it's got and flags. The post will keep sliding down with time. Edited: Clarifying.


It is function of time, votes, and flags.


I can't find the post but it is essentially:

Ranking = (votes)^(1/time) with some other bells an whistles.


sudo !! runs the previous line as root, in case you forgot to type sudo


More like "sudo !!" prepends sudo to the last history entry and executes the result. It may not run as root, depending on the complexity of the shell handiwork you did, and depending on /etc/sudoers.

I really, really, really hope that the author doesn't think "sudo !!" is some special kind of magic, and that he knows "echo !!" works the same way.

Also, there are keyboards with a "Home" key? Most people just press C-a.


Do you know where I can find a list of hotkeys along the lines of C-a? I personally created my own hotkey (shift left arrow) but learning standard ones would probably be good.


Most shells default to emacs keybindings:

  C-a beginning of line
  C-k kill text from cursor to end of line
  C-e end of line
  M-b move cursor backwards by a word
  M-f move cursor forwards by a word
  C-w delete backwards by a word
  C-h backspace (great when real backspace doesn't work)
  C-r reverse search through command history
(C-w works in Vim(insert mode) and Emacs, but kills me when I try to type it in a browser window to delete a word... Good-bye window and/or tab)

In zsh I actually have M-w bound to the normal backspace-by-a-word and C-w bound to the vim version which will do things like count '/' as a word separator so that I can easily backspace through sections of a path rather than be required to delete the whole thing (or nothing).


> (C-w works in Vim(insert mode) and Emacs, but kills me when I try to type it in a browser window to delete a word... Good-bye window and/or tab)

Control-Shift-T usually solves that problem for me in Firefox.


Hmm, FYI most of those work in the safari reply box. I think Apple put them for all Cocoa text fields not just terminal :-)


> I think Apple put them for all Cocoa text fields not just terminal :-)

It is the NSTextField that accepts those commands. The prefix NS stands for NeXTSTEP, so the functionality existed long before Cocoa.


Yea, but you have to hit Ctrl+Option or Cmd+Option (can't remember which off the top of my head) for Meta though, instead of just Option (which is what most people bind to Meta in Terminal.app or iTerm.app).


If you use bash, read the "Command Line Editing" section of "info readline".


You can also tweak the behavior of readline (for Bash and other applications) and custom make your own key combinations by editing your ~/.inputrc file. A random example from mine:

    # Insert double quotes & set cursor between them
    "\C-x\"": "\"\"\eb"
    #
    # Insert single quotes & set cursor between them
    "\C-x'": "''\eb"
See also the Bash manual:

http://www.gnu.org/software/bash/manual/bashref.html#Command...


Hi, I'm the author (admittedly still quite new to Unix). I did play around with the !! and realized it does a lot more. Thanks for clarifying though!

Edit: Typos


It's very powerful. There's more than just the !! for history, also. Check out http://www.catonmat.net/blog/the-definitive-guide-to-bash-co... .


I'd hope that most people just hit "<esc> I sudo !!<CR>".


You said Esc-0, first.


Yeah, I first tried...

grep ".jpg"

^C

ls | !!

...that worked too. Cool command to learn.

Thanks for the clarification, though. Original article was lacking.


[deleted]


Windmills do not work that way. Goodnight.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: