LinuxDevCenter.com

oreilly.comSafari Books Online.Conferences.

We've expanded our Linux news coverage and improved our search! Search for all things Linux across O'Reilly!

Search
Search Tips

advertisement

bash Tricks From the Developers of the O'Reilly Network

   Print.Print
Email.Email weblog link
Blog this.Blog this

Tony Stubblebine
Apr. 21, 2005 06:09 PM
Permalink

Atom feed for this author. RSS 1.0 feed for this author. RSS 2.0 feed for this author.

Every week the developers of the O'Reilly Network (that's me, three developers, and two admins) have a status meeting to check in with our key managers, decide or rearrange priorities, and work through problems. This is a dream meeting for managers, questions are answered and plans are laid.

It's fair to say that status meetings aren't a developer's dream. After several years of weekly meetings, ours were feeling stale. So we agreed to end the meetings with a round of tips and tricks. First up, bash tricks.

At the end of our meeting, the managers bailed and we stuck around to geek out over the tricks that make our work easier. Everyone had something to contribute. I can't recommend this enough! I've learned a lot from books like Unix Power Tools. But by sharing directly with your coworkers you get advice that's targeted directly to the work you do.

Here were our gems, the most useful tips that weren't already common knowledge among the developers.

pushd/popd

Bash will keep a history of the directories you visit, you just have to ask. Bash stores the history in a stack and uses the commands pushd and popd to manage the stack.

pushd dir - move the current directory onto the stack and change to the dir directory.

popd - pops the top directory off of the stack and moves you into it.

We're opening files all over the file system, internal code, vendor code, templates, configuration files, logs. Because of this we like the ability to take a detour on the file system and still navigate back to our working directory of the day. I think these commands are so useful that I alias'd them in my .bashrc


alias cd="pushd"
alias bd="popd"

Now the cd command manages the stack for me as well as changing directories. Aliasing popd to bd is an easy to remember and easy to type way to move back up the stack, think "change dir" and "back dir".

History

Bash keeps a history of the commands you've run. My group was already comfortable with the up and down arrows to navigate the history, !! to repeat the last command, and !foo to repeat the last command starting with foo.

Our newest admin had a better way, CTRL-R. That does command auto completion. Repeatedly pressing CTRL-R lets you tab through matching commands.

Home/End

CTRL-A takes you to the beginning of the line and CTRL-E takes you to the end of the line. This is probably basic shell knowledge, but I'm probably (hopefully) not the only person who didn't know it.

For Loops

We've got a cluster of machines that we'll sometimes need to loop through. Here's an example from our admins that checks uptime across our cluster.

$ for s in `cat server.list`; do ssh $s uptime; done;

Working with the Previous Command

Sometimes you want to run several commands on the same file, like run ls before deciding if that's the file you want to edit.


ls -l /long/path/to/file.txt
vi /long/path/to/file.txt

Bash provides a shortcut (!$) that holds the last word from the previous command. So in the above you could just write vi !$.

If your last command had a typo you can fix the command and rerun it with this construct, ^foo^bar. That replaces the first occurrence of foo in your command with bar.

Bonus Tip: use Awk

Our admins seem to think awk is pretty useful. And my boss thought it was so useful, he wrote a book on it. I can't keep any of the awk syntax in my head beyond printing out a column from a file.

The normal column delimiter is whitespace. So if you wanted to print out the seventh column in an Apache access log (that's the request url in my logs) you could write:

cat access_log | awk '{print $7}'

You can change the delimiter with -F. So if you wanted to list all the users on your system, you could pull them out of /etc/passwd with:

$ cat /etc/passwd | awk -F: '{print $1}'

The /etc/passwd delimiter is :, which I've indicated to awk with -F:.

We're doing vim tricks next.

Tony Stubblebine is an Internet consultant and author of Regular Expression Pocket Reference.

Comments on this weblog
Full Threads Oldest First

Showing messages 1 through 17 of 17.

  • No more worrying about cases
    2005-05-22 19:16:37  dustbo [View]

    The best bash tip I can share is very helpful when working on systems that don't allow filenames to differ only in case (like OSX and Windows):
    create a file called .inputrc in your home directory and put this line in it:
    set completion-ignore-case on

    Now bash tab-completion won't worry about case in filenames. Thus 'cd sit[tab]' would complete to 'cd Sites/'
  • directory stack
    2005-04-28 09:36:36  rarue [View]

    Long ago having aliased "pu" and "po" to pushd and popd, I've moved on to showing my current directory stack with

    alias d='dirs -v'

    and rolling through the stack with

    alias r='pushd +1'

    and single numerical values aliased to go to that directory that comes from the dir listing, eg.

    alias 3='pushd +3 > /dev/null ; dirs -v'

    Another single letter alias I like is "p", which I have used for displaying and setting my PATH variable, but the code is lengthy so I won't burden you with how

    p - 4
    p --
    p ++ /some/dir

    does what you want.


  • Command substitution
    2005-04-28 07:45:02  pkailasa [View]

    $ for s in `cat server.list`; do ssh $s uptime; done;


    Command substution is also done using $(command) notation, which I prefer to the backquotes. It allows commands to be nested (backquotes allow that too, but the inner quotes must be escaped using backslashes, which gets messy.



    For example:

    $ for s in $(cat server.list); do echo "$s: $(ssh $s uptime)"; done;

    or:

    # get the uptime for just the first server
    $ echo "$(date): $(ssh $(head -1 server.list) uptime)"

  • basename
    2005-04-24 17:59:30  bingalls [View]

    basename also supports extensions. Try this, to rename *.xml to *.wsdl (or *.cxx to *.cpp, etc)



    for i in *.xml;do;mv $i `basename $i .xml`.wsdl;done

    I tried this in zsh, so bash may complain that I have an extra ;.
    Be sure to upgrade to the latest bash, which has largely caught up with zsh features like **/* and programmable completion.
  • should be !$
    2005-04-22 10:38:20  pga-eti [View]

    Instead of $!, use !$, it works much better. :)

    $ echo asdf
    asdf
    $ echo !$
    echo asdf
    asdf
    $ echo $!

    $

    So $! is an empty variable, while !$ brings back the last argument from the last command.
    • should be !$
      2005-04-22 10:43:07  tonystubblebine | [View]

      So true. I updated the entry with your correction. Thanks.
  • ugu.com
    2005-04-22 06:12:31  msporleder [View]

    Get UNIX tips in your email every day, or enter some new ones to get emailed out to me and whoever else does this:
    http://www.ugu.com/sui/ugu/show?I=tip.today
    • ugu.com
      2005-04-22 06:13:18  msporleder [View]

      • ugu.com
        2005-04-22 06:13:53  msporleder [View]

        This would work better as a link.
  • vi key bindings
    2005-04-22 04:28:19  mrchucho@yahoo.com [View]

    set -o vi

    and you can navigate through the line using vi-style key bindings (e.g.g $ end of line, 0 start of line, etc.) Similarly, "ESC k" goes "up" in history and, "j" will go back down. "ESC /<string>" will search history for a string. And so forth!
    • vi key bindings
      2005-04-22 08:23:13  tonystubblebine | [View]

      This is a good one! Our other development team here (the people bringing you SafariU and the data that shows up on O'Reilly Radar) swear by it.

      I'm a vi user which is why I didn't know the home/end keymappings for Bash. Probably a good idea for any vi users to make this switch.
  • xargs and useless use of cat
    2005-04-22 02:14:07  aristotle [View]

    <blockquote>for s in `cat server.list`; do ssh $s uptime; done</blockquote>

    Do investigate xargs(1). The above example is easier written as

    xargs -i ssh {} uptime < server.list

    <blockquote>cat access_log | awk '{print $7}'</blockquote>

    That’s a useless use of cat there. You can just say



    awk '{print $7}' access_log

    Some people say they prefer cat(1) because that way they can expand or change the pipe easier. In that case, you can use a little-known feature of redirection operators: you can put them anywhere you want, ie



    < access_log awk '{print $7}'
  • More key bindings and tricks
    2005-04-22 00:40:26  FBoender [View]

    Bash will keep a history of the directories you visit, you just have to ask.

    You can also always go back to the previous directory you were in by typing cd - without the need to pushd the current directory. Using it more than once cycles between the current and previous directory.

    CTRL-A takes you to the beginning of the line and CTRL-E takes you to the end of the line. This is probably basic shell knowledge,

    I think it's actually common readline/emacs knowledge, and it works in much more programs than just Bash or a terminal. For instance, you can enable them in Gnome applications by adding the line
    gtk-key-theme-name = "Emacs" to the ~/.gtkrc-2.0 file.

    Other handy key bindings you can use are:
    • ctrl-u : Cut everything on the current line before the cursor.
    • ctrl-y : 'Yank' (paste) text that was cut using ctrl-u.
    • ctrl-w : Delete the word on the left of the cursor


    There's so much usefull knowledge hidden in Bash that, if you spend any time at the command line, you should really get yourself aquinted with. It saves incredible ammounts of time.

    Take for example something I wanted to do yesterday. I wanted to now the number of hits on a certain website. I could have installed a tool to parse the Apache access.log, but this was much easier:

    $ cat access.log | cut -d"[" -f2 | cut -d"]" -f1 | cut -d"/" -f2 | uniq -c
    28905 Mar
    16554 Apr


    Takes no more than a couple of seconds to write, but saves so much time.

    Try reading through the Bash man page. It's huge, but think of all the stuff you'll learn! Or read some online Bash scripting tutorials. Everything from gathering statistics from files to creating thumbnails of images (From the top of my head: for A in *; do convert $A -resize 140x140 th_$A; done) becomes a cinch.
  • Marc Hedlund photo Excellent
    2005-04-21 22:11:44  Marc Hedlund | O'Reilly AuthorO'Reilly Blogger [View]

    Fantastic post. Great idea for improving meetings, and great tips.
  • This week's Useless Use of Cat Award Goes to...
    2005-04-21 22:03:42  Randal L. Schwartz | O'Reilly Author [View]

    Hey, I like your useless use of cat... perhaps you should read why they're useless.
    • This week's Useless Use of Cat Award Goes to...
      2005-04-22 08:28:58  tonystubblebine | [View]

      I'm honored! Thanks Randal =)
  • Andy Lester photo Last argument
    2005-04-21 19:26:57  Andy Lester | O'Reilly AuthorO'Reilly Blogger [View]

    You can also use Esc-period and get the last parm of the previous line. You can repeatedly use Esc-period to scroll back through time with them. That turns out to be even better than $! because you can edit it once it shows up on your command line.

Showing messages 1 through 17 of 17.

Return to weblogs.oreilly.com.



Weblog authors are solely responsible for the content and accuracy of their weblogs, including opinions they express, and O'Reilly Media, Inc., disclaims any and all liabililty for that content, its accuracy, and opinions it may contain.

Creative Commons License This work is licensed under a Creative Commons License.



Advertisement

Sponsored by:

Sign up today to receive special discounts,
product alerts, and news from O'Reilly.
Privacy Policy >
View Sample Newsletter >
  • Youtube
  • http://www.youtube.com/OreillyMedia
  • Twitter
  • Subscribe
  • View All RSS Feeds >
O'Reilly Media

800-889-8969 or 707-827-7019
Monday-Friday 7:30am-5pm PT
©2011, O'Reilly Media, Inc.
All trademarks and registered trademarks appearing on oreilly.com are the property of their respective owners.
  • About O'Reilly
  • Academic Solutions
  • Contacts
  • Customer Service
  • Careers
  • Press Room
  • Privacy Policy
  • Terms of Service
  • Writing for O'Reilly
  • Community
  • Authors
  • Forums
  • Membership
  • Newsletters
  • RSS Feeds
  • User Groups
  • Partner Sites
  • makezine.com
  • makerfaire.com
  • craftzine.com
  • igniteshow.com
  • PayPal Developer Zone
  • O'Reilly Insights on Forbes.com