Bash

From usenix.org.uk
Jump to: navigation, search

Bash is my favourite shell.

Contents

functions in bash

Well, at work we often take a dated backup copy of a file that we might be editing. Some time ago I wrote a perl script that does some things to the file that is backed up. For example, if I was editing a zone file, why not increment the serial number inside it? This worked fine for a while, but later I decided it wasn’t such a good idea to have this on every single host that I work on. So, to cut a long story short, here’s the essential functionality implemented in bash so that it can exist in a .bashrc file, which is much easier to manage.

function bkp() {
 N=0;
 DATE=$( /bin/date +%Y%m%d );
 for i in $@ ; do
  D=$( /usr/bin/dirname $i );
  F=$( /bin/echo $i | /bin/sed -e 's/.*\///g' );
  if [ ! -d $D/old ] ; then
   /bin/mkdir -p $D/old;
  fi ;
  until [ 1 -eq 2 ] ; do
   let “N += 1″;
   C=$( /usr/bin/printf “%s/old/%s-%s-%.2d-%s” $D $F $DATE $N $USER );
   if [ ! -f $C ] ; then
    break ;
   fi ;
  done ;
  /bin/cp -p $i $C;
 done;
}

Hope this can be of some use to you too. This does have some obvious dependencies but this shouldn’t be too major.

time saving tricks

Another great time saver is alt-backspace. Give that a go, it deletes as far as the first non-alphanumeric character. Alt . is also useful, returns the last argument on the previous command.

Don't forget about the curly bracket expansion:

user@laptop:~$ echo file{a,b,c}
filea fileb filec

This is notably very useful when you intend to create a large tree of items with identical nodes within.

$ mkdir -p {beta,current,release}/{code,scripts,html,images}

This would create the nodes code, scripts, html and images within the top directories beta, current, release. Much more useful than creating these individual items.

useful keystrokes

combination result
alt-. last arg from previous command
alt-d delete the next word on the line
alt-backspace delete backwards one word
ctrl-w delete backwards a whole word until white space/punctuation
ctrl-k delete from the cursor to the end of the line
ctrl-u delete from the cursor to the start of the line
alt-f move to the end of the word
alt-b move to the start of the word
ctrl-e move to the very end of the line
ctrl-a move to the very start of the line

in practice

Something useful that's worth remembering is that () can create a sub-shell where the output can be piped elsewhere.

( cmd1 ; cmd2 ) | cmd3

sends output from both cmd1 and cmd2 are sent as stdin to cmd3.

This can be incredibly useful, especially if you're playing around mailing things via /usr/sbin/sendmail, for example, if you wish to send the contents of some output to someone/something and you wish to customise the headers a bit.

( /bin/echo -e "Subject: My favourite file\n\n" ; cat ~/.vimrc ) \
| /usr/sbin/sendmail -fme@example.test me@example.test

The huge advantage here is that the headers can be specified through the echo output, which will appear in front of the file contents when the sendmail program reads standard in.

input

Although not entirely related to bash, it's highly useful to add the following to your ~/.inputrc file so that annoying things like ~ don't appear when you press the delete key. This is often the case when the system you connect to does not have a friendly /etc/inputrc

"\e[3~": delete-char
"\e[1;5C": forward-word
"\e[1;5D": backward-word
"\e[5C": forward-word
"\e[5D": backward-word
"\e\e[C": forward-word
"\e\e[D": backward-word

This should enable the delete button for you, along with the ctrl-[left]/[right] buttons to go forward/backward a word. You might be more at home using alt-f/b key combinations however.

re-record not fade away

Another time save is the ability to repeat a command many times. This can be done by pressing alt-N (where N is a numeric). Follow this with a command or text and it will be repeated N number of times.

$ [alt-10]a
$ aaaaaaaaaa

You don't just have to limit to text, you can for example remove 10 words by pressing alt-10 ^w (^w being ctrl-w)

The huge benefit of things like this is that most of the functionality of the BASH command line is due to libreadline which is linked in many other applications.

bash redirection

One of the very useful things you can do from within a script is capture it's output, rather than from the caller, which may become a bit of command line clobber that you don't want to record in your crontab.

$ my_script 2>&1 > /var/tmp/my_script_${HOSTNAME}_$$_${USER}.log

You can put all this into the script itself

#!/bin/bash

LOG=/var/tmp/my_script_${HOSTNAME}_$$_${USER}.log

exec 2>&1 1>${LOG}

So, everything beneath these lines will be captured via the LOG file.


Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox