Unix Shell

From Shrubbery

Jump to: navigation, search


Contents


Other Pages

One liners

Get the filename and directory of the currently running script

SCRIPT_NAME=${0##*/}
SCRIPT_DIR=`dirname $0`

Diff two directories, only show which files are different

diff -rq somedir someotherdir

Merge stderr into stdout

Use 2>&1, for example:

somecommand 2>&1 > someoutput.log

Get the extension of a file

In bash, use ${var/*./}

For example:

myfile=thefile.txt
myext=${myfile/*./}

Results in myext being '.txt'

Shell Programming

Start with a shebang!

  • Shell scripts should begin with a 'shebang'. Usually #!/bin/sh or #!/bin/bash.
  • To make the script executable, simply chmod +x myscript
  • File extensions don't matter in Linux and Unix. You can name the script 'myscript.sh' or just 'myscript' and it will make no difference, other than the fact that you will have to type the whole file name to execute it.
  • Shell scripts must use Unix/Linux-style line feeds! Even under Cygwin this is true. To convert a shell script file to Unix line feed format, use dos2unix.

See Start off with a shebang

Launching a nested shell from a shell script

Nested shells can be really useful for setting up environment variables, PATH, and LD_LIBRARY_PATH in a clean way. You could just source in a shell script that sets environment varaibles, etc, but in the nested shell it is much easier to return to the un-touched environment by typing exit.

#!/bin/bash
... set up environment variables and PATH ...
... exports ...
exec $SHELL

Cygwin compatibility

If you are using Cygwin, you need to do a few extra things to 'path names' and other structures before invoking non-Cygwin commands. ANT is a good example because it is run under Java, which doesn't know about Cygwin paths.

Here is an example of setting ANT_HOME from a shell script:

#!/bin/sh
ANT_HOME=/cygdrive/c/java/apache-ant-1.6.5
JAVA_HOME=/cygdrive/c/java/jdk1.5.0_10
PATH=$ANT_HOME/bin:$JAVA_HOME/bin:$PATH
ANT_HOME=`cygpath --mixed "$ANT_HOME"`
JAVA_HOME=`cygpath --mixed "$JAVA_HOME"`
export ANT_HOME
export JAVA_HOME

Of course, this won't work on Linux, so it could be made more portable like this:

#!/bin/sh
UNAME=`uname`
case "$UNAME" in
    CYGWIN*)
        ANT_HOME=/cygdrive/c/java/apache-ant-1.6.5
        JAVA_HOME=/cygdrive/c/java/jdk1.5.0_10
        ;;
    *)
       ANT_HOME=/opt/apache-ant-1.6.5
       JAVA_HOME=/usr/java/jdk1.5.0_10
       ;;
esac

PATH=$ANT_HOME/bin:$JAVA_HOME/bin:$PATH

case "$UNAME" in
    CYGWIN*)
        ANT_HOME=`cygpath --mixed "$ANT_HOME"`
        JAVA_HOME=`cygpath --mixed "$JAVA_HOME"`
        ;;
    *)
        # Nothin' doin on linux.
        ;;
esac

export ANT_HOME
export JAVA_HOME

Note:

  1. PATH is not converted. That's because Cygwin uses PATH.
  2. JAVA_HOME and ANT_HOME are converted 'after' PATH is set because ant doesn't know about Cygwin's path system, but Cygwin bash does.

Script name and script path

It is often useful to have the name of the currently running script and the path it is located in as shell variables. Here is an example:

#!/bin/sh
SCRIPT_NAME=${0##*/}
SCRIPT_DIR=`dirname $0`

See Start off with a shebang

Full path names

To get the full path name from a relative path name:

RELATIVEPATH=".."
ABSPATH=`cd $RELATIVEPATH && pwd`

Note that the 'cd' command inside the back-ticks does not affect the current directory of the running script.

To get the full path of the parent directory of the current script:

#!/bin/sh
SCRIPT_DIR=`dirname $0`
PARENT_DIR=`cd $SCRIPT_DIR/.. && pwd`
Personal tools