Hacker News new | past | comments | ask | show | jobs | submit login
Level Up Your Shell Game (viget.com)
91 points by dce on Oct 24, 2013 | hide | past | favorite | 46 comments



I didn't see Ctrl-r, but I've found that to be the most insanely useful shortcut.

Ctrl-r = reverse history search. Type a partial command after Ctrl-r and it'll find the most recent executed command with that substring in it.

Press Ctrl-r again, jump to the next oldest command containing your substring. Did you accidentally press too many Ctrl-r? Press backspace to move forward in history.


A complementary tip for Ctr+R is to tag long reusable commands with a comment in the end, e.g.,

find . -name "*.png" -print0 | xargs -0 -P8 pngquant --ext .png --force 256 #optimizepng

(if you’re using zsh, you have to enable INTERACTIVE_COMMENTS option first; just run set -k)


Cool tip, did not know that, though I prefer to put long reusable commands in script files, in part so I can comment them to better remember what everything is doing.


Thanks! I didn't know about INTERACTIVE_COMMENTS.

Adding a comment there is a neat trick. It also works with bang searches (!?), almost like creating a temporary ad-hoc alias:

    find . -name "*.png" -print0 | xargs -0 -P8 pngquant --ext .png --force 256 #optimizepng
    ... many other commands, time passes ...
    !?optimizepng


Since I've switched to zshell, I've found that I haven't used Ctrl-r much at all. The intelligent history feature does it for me. For example:

If earlier I had a long command like `mvn clean test && mvn deploy -P release`, I can just type `mvn v` and press up on the arrows. zsh will present only history entries that start with what I've typed. Insanely useful!


The same thing can be done in bash:

## arrow up

"\e[A":history-search-backward

## arrow down

"\e[B":history-search-forward

(in .inputrc)


I prefer mapping those to page up and page down.


C-s moves forward in history, but you have to type it twice to begin with, once to toggle the mode, and once to actually move forward.

Backspace normally just deletes the last character in your incremental search string.

And be sure that C-s / C-q aren't set up for terminal flow control with something like:

    stty start undef stop undef


Many of the solutions they highlight can actually be solved with this. Surprised that it wasn't included.


IMO the aliases for git should be in ~/.gitconfig instead. I have a bunch of these, like:

    [alias]
    br = branch
    co = checkout
    ci = commit -v
    sci = svn dcommit --interactive
    cp = cherry-pick
    l = log --pretty=oneline --abbrev-commit
    l3 = log --pretty=oneline --abbrev-commit -n3
    lm = log --pretty=oneline --abbrev-commit master..
    rc = rebase --continue
    st = status -sb
    squash = !git rebase -i --autosquash $(git merge-base master HEAD)
Also, I prefer to set aliases in my ~/.functions instead of in ~/.bash_profile or ~/.bashrc. I find that this makes it easier to move the .functions file from one machine to another, especially on a lab/test machine with a shared account where I shouldn't be modifying things in the shared ~/.bashrc. To make this work, you can add this to your ~/.bashrc or ~/.bash_profile:

    if [ -f ~/.functions ]; then . ~/.functions; fi
This will source your .functions file if it exists when your .bashrc is run.

A tweak to the "editbash" suggested alias will make it so that you don't have to reopen your terminal. My equivalent alias is "vif", for "vi .functions":

    alias vif='vi ~/.functions; . ~/.functions'
Note that the second command (after the semicolon) sources the modified .functions file.

Lastly: brevity is king. I love 'alias psgrep="ps aux | grep"', since I use it several times a day, but to "level up your shell game", keep it short. My alias for this command is "psg". The other alias that I use all the time is "d" -- "alias d='ls -lFh --color --group-directories -v'".


Did you know you can make your own git commands, and I don't mean just aliases?

Write a script called git-mycommand, and you can invoke it with 'git mycommand'. Tab completion works too, at least for bash + bash_completion.


Yes, I have written some of those too. Just make sure the script is in your PATH. I drop them in ~/bin/ -- which reminds me of another thing you should have in your ~/.bash_profile, if it isn't already in the template provided by your system:

    if [ -d $HOME/bin ]
    then
        PATH=$PATH:$HOME/bin
    fi


Why exactly do you love 'alias psgrep="ps aux | grep"' ? What does it get you that pgrep doesn't (or, if you need more information, 'ps u `pgrep <name>`')?


I've worked on a lot of systems that don't have pgrep.

'ps aux | grep' works everywhere


My favorite shell trick (not in the link) is this: ~-

Tilde-hyphen expands to the previous directory you were in, and of course "cd -" returns you to your previous directory, so I put them together all the time.

Here's an example workflow (with a fake PS1):

  mac:/Users/me/Projects/my_new_app$ cd ~/.pow

  mac:/Users/me/.pow$ ln -s ~- .

  mac:/Users/me/.pow$ cd -

  mac:/Users/me/Projects/my_new_app$
Now I can continue working on my app.

<disclaimer>

That's bit of a contrived example above. Here's a more realistic way to do a symlink for pow:

  mac:/Users/me/Projects/my_new_app$ ln -s `pwd` ~/.pow/
</disclaimer>


Save the earth, fork less:

    ln -s $PWD ~/.pow
(Interesting tip about ~-, didn't know that one)


The command line navigation commands are just what any Emacs user would expect. vi users can set their $EDITOR to 'vi' to get those commands.

What do you mean you've never used Emacs? mumble whippersnappers mumble


Use `set -o vi` to get vi navigation commands on the command line.

EDIT: In bash, that is. It's `bindkey -v` in zsh.


Do it in .inputrc like this:

set editing-mode vi

Now any executable that uses readline will have vi editing commands on its command line. mysql, psql, etc.

Do as much of your command line editing configuration in .inputrc as possible, and you'll have it everywhere.

EDIT: man readline


set -o vi works in zsh as well.



It's probably worth mentioning that all the delete functions he points out(all of them for that matter, ctrl-k, etc) are actually cut's, so you can paste them back as well. I find Ctrl-u especially useful when I'm halfway through with a command, then I realize I wanted to do something else before executing said command, so I cut it- then paste it back when I need it. * Ctrl + y to paste anything back


readline also seems to have a "kill ring":

    $ aaa ^U
    # now "aaa" is the only thing in the kill ring
    $ bbb ^U
    # now kill ring is ["aaa", "bbb"]
    $ ccc ^U
    # now kill ring is ["aaa", "bbb", "ccc"]
    $ ^Y
    $ ccc
    # alt+y cycles through the kill ring
    $ bbb Alt+Y
    $ aaa Alt+Y
    $ ccc Alt+Y
    $ bbb
etc. This likely feels completely natural if you're an emacs user. I don't know what the equivalent vi thing is.


> Note: you’ll need to open a new Terminal window for changes in ~/.bash_profile to take place.

Alternatively, you can just do '. ~/.bash_profile' or 'source ~./bash_profile'.


  alias refresh-bash="source ~/.bash_profile"


Interestingly, relatedly, a lot of the emacs style keybindings (ctrl-a, ctrl-e, ctrl-k, etc) are system-wide in OSX. I prefer vim as my daily editor, but it is often useful. You can also make the bindings even more emacsy if you want.

http://irreal.org/blog/?p=2063


There’s a link to one of the related files from your link, but folks might also find the rest of my article about this from 2006 interesting:

http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html

Also cf.:

http://www.hcs.harvard.edu/~jrus/site/system-bindings.html

http://www.hcs.harvard.edu/~jrus/site/selectors.html

https://github.com/jrus/cocoa-text-system/tree/master/KeyBin...


aliasing git shortcuts seems more appropriate for git config:

https://git.wiki.kernel.org/index.php/Aliases

...after aliasing git to 'g' in your shell config, of course :)

    alias g='git'


Then you need a space after the g.


When you execute a command that takes a long time to run and you want to send it to the background you can do:

ctrl + z

then, to send it to the background:

bg

and, to get it back from the background:

fg

Also, I really like to use "for", like:

// get the size of each file or directory in the current directory

for i in `ls -1`; do du -hs $i; done;


I don't understand your last line. How is it different to "for i in *; blah"? Or even just "du -hs ."?


It was just an example...

instead of "ls -1" you could use any other command that returns a list

The "du -hs ." will only return the size of the current directory, but that was also an example. You could use any other command that you wanted to perform over each item in the list returned by the first command.

Not sure if this is clear enough, please let me know.


I prefer to use inputrc instead of aliases. Put the following into your .inputrc

    "\C-gs": "git status -sb "
Then, for example, after pressing Ctrl-g, s "git status -sb " will appear in your prompt. Much more readable than lots of two or three letter aliases. You can see the complete list of my shortcuts on my GitHub - https://github.com/grn/dotfiles/blob/master/inputrc


I don't like rebinding C-g, as that's the 'cancel' key for things like incremental search (in emacs bindings).


Good point! Interestingly I managed to work without it somehow. I just checked that C-g C-g works as cancel when those binding are present.


They should really mention which shell and terminal emulator they are using. Not everyone is using the same "Unix command line".


Fair point. FWIW, we're all on OS X, running bash, zsh, or fish on either Terminal.app or iTerm2.


Control-Left and Right switch workspaces for me. A giant pain in the ass, because the normal word-jump shortcut, Option-Left/Right, just drops a [C/[D into the shell on iTerm. The stupid thing is, if I shell into an Ubuntu machine, it works fine.


You can probably set that up in .inputrc. Pressing Ctrl-V in a terminal before pressing your ctrl+left or ctrl+right arrow will type the initial escape character literally so you can see what the key sequence is (e.g. something like \e[1;5D).

Alternatively, you could change your workspace bindings to Control+[some other modifier].


Here is a rule for how to level up your shell/editing game. If you ever touch your arrow keys, you are doing something wrong.

> ctrl + left arrow Moves the cursor to the left by one word > ctrl + right arrow Moves the cursor to the right by one word

Alt + b and Alt + f are also aliases for the same action.


uhh.... So what's wrong with doing the exact same thing with arrow keys? isn't that more natural and convenient?


Your hand has to move a few inches. It wastes time. You can optimize it out of your workflow.


I like the commands, especially the ssh one, which I didn't know before and will certainly use in the future.

I also enjoyed the format of the article. A whole dev team each contributing their own piece to a blog post provides a lot of different voices and styles in a concise way.


I knew about the sudo !! but the sudo !$ will come in handy! thanks!


Ctrl-t will flip two words. Not very useful but pretty cool.


ctrl + l

to clear the screen, instead of typing "clear" is pretty useful too.




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

Search: