Unix Commands

These notes do not attempt to be complete instructions for these commands, but are observations and hints. There are links to the Open Group's Single Unix Specification man pages.

 
TOP
 
basename dirname ed grep wc

basename


DESCRIPTION

Strip directory and optional suffix from filenames


With POSIX shells (ksh, bash, ash, etc.), there is no need for the (external) basename command.

To extract the filename from a path, you can use parameter expansion:

path=/home/user/filename.txt
echo ${path##*/}

To remove a suffix:

echo ${path%.txt}

To do both:

path=/home/user/filename.txt
base=${path##*/}
echo ${base%.txt}

The following function is a POSIX-compliant version of basename that uses no external commands:

basename()
{
    _basename "$@" &&
    printf "%s\n" "$_BASENAME"
}

_basename() ##
{
    [ "$1" = "--" ] && shift 
    fn_path=$1
    fn_suffix=$2
    case $fn_path in
        ## The spec says: "If string is a null string, it is
        ## unspecified whether the resulting string is '.'  or a
        ## null string. This implementation returns a null string
        "") return ;;
        *)  ## strip trailing slashes
            while :
            do
              case $fn_path in
                  */) fn_path=${fn_path%/} ;;
                  *) break ;;
              esac
            done
            case $fn_path in
                "") fn_path="/" ;;
                *) fn_path=${fn_path##*/} ;;
            esac
            ;;
    esac
    case $fn_path in
    $fn_suffix | "/" ) _BASENAME="$fn_path" ;;
        *) _BASENAME=${fn_path%$fn_suffix}
    esac
}
basename.html updated 2010-06-18

dirname


DESCRIPTION

Strip last component from file path


With POSIX shells (ksh, bash, ash, etc.), there is no need for the dirname command.

To strip the filename from a path, you can use parameter expansion:

path=/home/user/filename.txt
echo ${path%/*}

The following function is a POSIX-compliant version of dirname that uses no external commands:

dirname()
{ 
    _dirname "$1" && printf "%s\n" "$_DIRNAME"
}

_dirname()
{ 
    [ "$1" = "--" ] && shift 
    _DIRNAME=$1;
    strip_trailing_slashes;
    case $_DIRNAME in 
        "")
            _DIRNAME='/'
	    return
        ;;
        */*)
            _DIRNAME="${_DIRNAME%/*}"
        ;;
        *)
            _DIRNAME='.'
        ;;
    esac;
    strip_trailing_slashes;
}

strip_trailing_slashes()
{
    while :
    do
       case $_DIRNAME in
          */) _DIRNAME=${_DIRNAME%/} ;;
          *) break ;;
       esac
    done
}
dirname.html updated 2010-06-18

ed


DESCRIPTION

ed is a line-oriented text editor. It is used to create, display, modify and otherwise manipulate text files.


Use ed with caution.

Actually, use all commands with caution, but I single out ed because, unlike most Unix commands, it operates on files in situ.

Most commands (sed, awk, tr, head, tail, cat, etc.) send the output to stdout, which is usually the terminal or a file. When sent to a file, the output must be sent to a file other than the one being used for input (unless you append the output to the file, which is rarely what you would want).

The output file can then be moved over the original file. When testing the script, you can omit the replacement of the original file to check that the script has done what you want. Or you can back up the file before it is overwritten (if you are using GNU mv, just use the -b option).

ed.html updated 2010-06-18

grep


DESCRIPTION

Grep searches the named input FILEs (or standard input if no files are named, or the file name "-" is given) for lines containing a match to the given PATTERN.


Grep is good for searching files, but not a good tool for finding out whether one string is contained within another.

Rather than using:

echo "$string1" | grep "$string2" > /dev/null

a case statement can do the job without calling an external command:

case $string1 in
    *$string2*) ;;
    *) false ;;
esac
grep.html updated 2010-06-18

wc


DESCRIPTION

Print line, word, and byte counts for each FILE, and a total line if more than one FILE is specified. With no FILE, or when FILE is -, read standard input.

Options -c -w and -l specify whether to print the count of one or more of characters, words, or lines. If no option is given, all three are printed.


If you want to use the output of wc in a calculation, redirect or pipe the file[s] into the command, and store the output in a variable:

lines=`wc -l < FILE`

lines=`cat *.txt | wc -l`

Some versions of wc will put spaces before the output, and this can cause problems. The spaces can be removed by enclosing the result in an arithmetic expression:

lines=$(( `wc -l < FILE` ))

lines=$(( `cat *.txt | wc -l` ))

Or you can set the results into the positional parameters, which has the advantage of removing any whitespace, as well as giving you the word count and character count if you want them:

set -- `wc FILE`
lines=$1
words=$2
chars=$3

set -- `cat *.txt | wc`
lines=$1
words=$2
chars=$3
wc.html updated 2010-06-18