Heiner's SHELLdorado
Shell Tips & Tricks (Intermediate)
SHELLdorado - your UNIX shell scripting resource
HomeGood Shell Coding PracticesExample Shell ScriptsShell Scripting LinksShell Scripting Tips+TricksShell Scripting Articles

Tips&Tricks Home
  Beginner
  Intermediate
  Script Programmer
  Advanced

Submit a new Tip

  Previous Tip Top Next Tip
Providing default file name arguments to scripts
Level: Intermediate Submitted by: ??? URL: none
If a shell script frequently works with files of a special type
(i.e. "*.txt")
a script may use all files of this type in the current directory as default
if no file name is specified.

Example:

# changetextfiles
...
# If no arguments are specified, use all files matching "*.txt"
[ $# -lt 1 ] && set -- *.txt

...
      

Previous Tip Top Next Tip
Comfortable directory list
Level: Intermediate Submitted by: ??? URL: none
# Append to .bashrc or call it from there.
# Save some typing at the command line :)

# longlist a directory, by page
# lo [directoryname]
lo () {
      if [ -d "$1" ] ; then
         ls -al "$1" | less
      else
         ls -al $(pwd) | less
      fi
}

# Same as above but recursive
lro () {
      if [ -d "$1" ] ; then
         ls -alR "$1" | less
      else
         ls -alR $(pwd) | less
      fi
}
export -f lo lro

      

Previous Tip Top Next Tip
Search and replace with extended regular expressions
Level: Intermediate Submitted by: Felix.Wiemann@gmx.net URL: http://www.ososo.de/extreg/
To perform search-and-replace operations
with extended regular expressions, copy
and paste the following script to
/usr/local/bin/extreg or $HOME/bin/extreg:

#!/bin/sh
if [ $# -gt 1 ]; then
   perl -we '$/="'"$2"'";while(<>){'"$1"';print $_}'
else
   perl -we 'undef $/;$_=<>;'"$1"';print $_;'
fi

Syntax: extreg regexp [separator]

"regexp" are one ore more extended regular expressions, separated by
semicolon.

"separator" is an optional separator,
see perlvar(1), section
$INPUT_RECORD_SEPARATOR. The data which
has to be processed is divided into
(with the separator ending) blocks, on
which the regular expressions are applied.

If you want to be portable you should
invoke perl directly. "extreg" is primarily meant to be used in your
private scripts or in interactive shell mode.
      

Previous Tip Top Next Tip
Indenting lines
Level: Intermediate Submitted by: ??? URL: none
To indent all input lines with four blanks use

    sed 's/^/    /'

This substitutes the "start-of-line" marker "^" with four spaces.
Since the marker will not disappear, the input

    this is
    a text

will be rewritten as

    ____this is
   ____a text

(The "underscore" character "_" in this example will be a non-visible
space character)


      

Previous Tip Top Next Tip
How to execute a script for each logout
Level: Intermediate Submitted by: ??? URL: none
Sometimes it's useful to execute a command after each
logout, i.e. to cleanup temporary directories, or to log
working hours.

This is the way to make the shell execute the script
$HOME/.atexit after each logout:

 1. Insert this line at the beginning of the file
    $HOME/.profile:

        trap ". $HOME/.atexit" 0

 2. Create a file named "$HOME/.atexit", that may contain
    arbitrary shell commands, i.e.

       $ cat > $HOME/.atexit
       echo "Good bye $LOGNAME, the time is `date`"
       ^D

That's it! After the next login, the shell will execute
the contents of the file "$HOME/.atexit".

NOTE: this will not work for C-Shell dialects, i.e. TCSH

      

Previous Tip Top Next Tip
Case-insensitive pattern matching
Level: Intermediate Submitted by: ??? URL: none
Some commands do not have a way to match text without considering
the character case, i.e. "awk":

    awk '/abc/ { print $1 }'

will find lines containing "abc" but not "ABC" or "aBc". (Of course
in this case you could use "grep -i", but there are situations you
cannot use "grep").

With a little typing you can make this pattern case-insensitive:

    awk '/[aA][bB][cC]/ { print $1 }'

This matches all combinations of "abc" with any character case.
You can always rewrite a constant expression like /pattern/
like this: /[pP][aA][tT][tT][eE][rR][nN]/. Just replace
each character "c" with the expression "[cC]" meaning:
    either a small "c" or a upper-case "C"


      

Previous Tip Top Next Tip
Split a file into multiple files depending on a key value
Level: Intermediate Submitted by: janis.papanagnou@hotmail.com URL: none
You have, e.g., a log file to collect logs of different sources;
then you
want to separate the log records depending on a key value defined in the
log data records (the key might identify the source); records with equal
keys should go into the same file.
The program can, of course, be used for other applications than log files,
too.

A nice task for a one-liner... !!

# splitlog.sh - split logfile into multiple logfiles
#
# Depending on some key value in the first column of the logfile defined
# in the argument, it will be split into a set of logfiles, one for each
# key.  If no argument is specified, stdin is used.
#
# Usage: splitlog.sh [ logfile ]
#
# Janis Papanagnou, 2002-11-22

awk -v logfile=${1:-"stdin"} '{ print > logfile"-"$1 }' "$1"

: '--- An example to illustrate...
A file "logfile" with keys A, B, C, and containing the lines, e.g.:
        A 489257 8957 38tgzg75hg g5hg 5gh27hg 75gh 5hg    0
        C 8 c83h5g 85gh 5hg5hg h 8h8gh t2h gtj2            1
        B 459 wef2 eruhg uiregn euignutibngtnb ioj         2
        B 489257 8957 38tgzg75hg g5hg 5gh27hg 75gh 5hg    3
        A 459 wef2 eruhg uiregn euignutibngtnb ioj         4

will be split into three files "logfile-A" (only lines with key A):
        A 489257 8957 38tgzg75hg g5hg 5gh27hg 75gh 5hg    0
        A 459 wef2 eruhg uiregn euignutibngtnb ioj         4
"logfile-B" (only lines with key B):
        B 459 wef2 eruhg uiregn euignutibngtnb ioj         2
        B 489257 8957 38tgzg75hg g5hg 5gh27hg 75gh 5hg    3
and "logfile-C" (only lines with key C):
        C 8 c83h5g 85gh 5hg5hg h 8h8gh t2h gtj2            1
----'
      

Previous Tip Top Next Tip
Copy directory and subdirectories
Level: Intermediate Submitted by: hk-support@iscs-i.com URL: none
#!/bin/ksh
#
tarpipe ()
{
   # create dest if not already
   [ ! -d "$2" ] && mkdir "$2"
   # copy it over
   tar cCf "$1" - . | tar xCf "$2" -
}

tarpipe "$1" "$2"
      

Previous Tip Top Next Tip
Copy directory and subdirectories (2)
Level: Intermediate Submitted by: ??? URL: none
The following command can be used to copy directories including
subdirectories from one place to another:

src=$HOME
dst=/tmp     # example, must be absolute path

# Create destination directory if it does not exist already
[ -d "$dst" ] || mkdir -p "$dst" || exit 1

cd "$src" &&
    find * -print | cpio -pdm "$dst"

This reads and writes the data only once, and therefore usually is more
efficient than using "tar".
      

Previous Tip Top Next Tip
Making xterm titles match current directory
Level: Intermediate Submitted by: ??? URL: http://gypsy.rose.utoronto.ca/people/David.html
There are several parts to this.  First, you need a program that I've
called "title.c" that takes one or two arguments and makes them the title
of the open window and the shrunk window respectively.  That program is
included below.  The second thing you need are clever cd replacement aliases
that automatically adjust the window title whenever you change directory.

Here's the program:
---
# Copyright 1999 by David Drascic.
# Permission to use and modify granted,
# so long as my name is included in the
# modified code somewhere with credit.
#
# title.c: prints out escape sequences
# so that sun and xterm windows will
# change their titles, both open and
# shrunk.

#include <stdio.h>
#include <stdlib.h>

#define ESC '\033'
#define BACKSLASH '\\'

void main(argc, argv)
    unsigned int argc;
    char **argv;
{
    char *getenv();
    char *term;

    if ((term=getenv("TERM"))==NULL)
      {
        printf("%s: unable to find TERM environment variable\n",
                        argv[0]);
      }

    else if (strncmp(term, "sun", 3)==0)
      {
        /* Sun window title */
            printf("%c]l%s%c%c", ESC, argv[1], ESC, BACKSLASH);

         /* Sun icon title; use 2nd arg if there is one */
            printf("%c]L%s%c%c", ESC, argv[argc-1], ESC, BACKSLASH);
      }

    else if ( (strcmp(term, "xterm")==0) || (strncmp(term, "iris", (size_t)
    4)==
0) )
      {
         /* xterm window title */
            printf("%c%c1.y%s%c%c", ESC, 'P', argv[1], ESC, BACKSLASH);

        /*  xterm icon title */
            printf("%c%c3.y%s%c%c", ESC, 'P', argv[argc-1], ESC, BACKSLASH);

      }
}
---

Here are the three aliases I set in my .login file:
---
# "." is the new "cd" command.

alias .   'set dot=$cwd;cd \!*; if (-e .cdrc) source .cdrc; title "`hostname`:
$cwd" `hostname`'

# ".." takes you up one directory level

alias ..  '. ..'

# "," with an arg cds to that arg, otherwise it returns to the previous
directory

alias ,   'set goto=(\!* $dot); . $goto[1]'
---


      

   
Copyright © 1998-2014 Heiner Steven (heiner.steven@shelldorado.com)