Unix command line pebbles

2012-01-13

I always find that “sitting next to someone new” is an interesting and revealing experience. I learn new things, they learn new things. Over the years I’ve accumulated a bunch of tricks about using the command line, using vi, and even using emacs. The thing I’m talking about are things can’t really be learned in a formal context, they are too small and there are too many of them. Yet collectively they form part of the fabric of what it means to be a vi user or a shell programmer or whatever. Picking them up and passing them on by sitting next to someone is the only way I know to spread them. Well, maybe this blog post is a start.

Here’s a few I’ve recently picked up or passed on:

cd -

It changes directory to the last directory that you changed from. It’s /bin/bash not /bin/sh (so I personally would avoid writing it in scripts). I think someone alleged that this was undocumented, but in fact I recently checked and it is in fact documented in the builtins section of the /bin/bash man page, which is huge.

It’s useful when you want to cd to some directory to run a command, but then cd back.

Line 25 of the runlocal script in ScraperWiki used to do just that in order to start a service from within a different current directory:

cd ../services/scriptmgr
node ./scriptmgr.js &
cd -

Because I don’t like writing bash-specific scripts, I changed this to use a subshell, with round brackets:

(
    cd ../services/scriptmgr
    node ./scriptmgr.js &
)

A subshell is used to run the code between the round brackets, and it is just a forked copy of the shell. It has exactly the same environment (environment variables, open files, and so on), but is in another process. Since the Current Working Directory is specific to the process, changing it in the subshell has no effect on the outer shell, which carries on unaffected after the subshell has returned. So that’s something I’ve passed on recently.

cp foo.cnf{-inhg,}

This is the same as cp foo.cnf-inhg foo.cnf. It copies a file by removing the -inhg extension from its name. ScraperWiki stores some config files in Mercurial (the -inhg versions), and they are copied so they can be edited locally (the versions without the -inhg suffix). I’m sure this has all sorts of evil uses.

sudo !!

Of the things I’ve picked up recently, this is my favourite. I like how some of these tips are a combination of things that I already knew individually but hadn’t thought to combine. Of course I know that sudo thing runs thing as root, and I did once know that !! is the /bin/csh mechanism (stolen by /bin/bash) for executing the previously typed command. In combination, sudo !! runs the previously typed command as root. Which is perfect for when you typed pip install thinginator instead of sudo pip install thinginator.

Ctrl-R

The favourite thing I seem to have spread seems to be Ctrl-R. (in /bin/bash) you press Ctrl-R, start typing, and bash will search for what you type in your command history; press Return to execute the command or Ctrl-R to find the next older match. Press Ctrl-C if you didn’t really want to do that.

Credits

One of the @pysheff crowd for sudo !!; can’t remember whether it was @davbo or @dchetwynd.

Ross Jones for cd -;

Bitbucket user mammadori “{-ext,}”.

If you enjoyed this post, you may also like Mark Dominus’ semi-rant on the craptastic way to do calculation in shell scripts. Huh, now I feel compelled to that Mark gets it wrong about GNU Shell; arithmetic expansion is not a GNU innovation, it comes from POSIX, having been slightly mutated from an earlier Korn Shell feature. And if he had comments I would’ve said that on his “blag”.

About these ads

11 Responses to “Unix command line pebbles”

  1. Gareth Rees Says:

    Is there a reason for the ./ in node ./scriptmgr.js & (Does the node command have a search path that you want to suppress, for example?)

  2. Clive Says:

    Are you aware of pushd and popd? They’re like “cd -“, only with a deep stack for multiple digressions.

  3. joe Says:

    Alt-period may be the greatest little-known bash feature i use regularly. even better than ctrl-R / !!.

  4. Neil Bowers Says:

    When you picked up !!, did you also pick up !$ and !*

    !$ is the last argument of the previous command. So

      % vi foobar.c
      % gcc !$
    

    You can also go back a number of entries in your history:

      % vi !-2$
    

    Will edit the last argument from two commands back in your history.

    !* is all of the arguments of the previous command.

      % vi foo.c bar.c
      % lint !*
    

    And you can apply substitutions to !! as well:

      % echo foo.c bar.c
      % !!:gs/.c/.h/
      echo hello.h foo.h bar.h
    
    • drj11 Says:

      I think at one point I in theory knew about those from a thorough reading of the manual, but I’ve never used them in anger. “gcc !$” seems particular useful, I’ll try and remember to try it.

    • davbo Says:

      oooo I knew about !$ but not the history bit. That looks very handy.

      I find these tips to be a godsend when on an ssh to machines which appear to use the tin can & string networking protocol.

      Thanks Neil.


  5. Thanks. I recently found about the Ctrl-R and cd – and they are my best friends now. And I even called them “two most useful” commands :)

    http://cmdlinetips.com/2011/10/two-most-useful-commands-if-you-live-on-the-linuxmacos-terminal/

    I am also picking up a few tricks from the comments. I


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: