Print service provided by iDogiCat: http://www.idogicat.com/
home logo





Home > IT > Programming > Bash Useful Scripts

Bash Useful Scripts

iDog

Change File Extensions


#!/bin/bash

if test $# -lt 2 ; then
    echo "$0 src_ext dest_ext"
    exit
fi

for fname in *.$1 ; do
    echo "Moving: " $fname
    newname=${fname%%.*}

    if test -f $fname ;  then
        mv $fname $newname.$2
    fi
done

Make a script run from anywhere correctly

How to handle paths in a script? If the relative paths are fixed, but the whole project can be deployed anywhere... In this case, we need to get the absolute path of the script and deduce out the paths of other files from it:


cd $(dirname $0)
SCRIPT_DIR=$(pwd)


anotherDir=${SCRIPT_DIR}/../another_dir
cd ${anotherDir}

[NOTE]:

The commands of getting dir and filename from whole path is very useful:

  • dirname - get dir, strip filename
  • basename - get file name, strip dir and suffix.

Make string comparison robust

Doing it in following way

if test "x${myStr}" = "xexpected_value" ; then
instead of
if test "${myStr}" = "expected_value" ; then
makes it robust. Otherwise, when the $myStr is empty, the script fails.

diff files and make a line-by-line comparison

diff file1 file2 > tmp
grep '^<' tmp > tmp1
grep '^>' tmp > tmp2
paste tmp1 tmp2 | sed "s/   /^M/g" > result

Note that in the sed command, the first is a tab, entered by pressing <ctrl>-<tab>; the second one (^M) is a line break, entered by pressing <ctrl>-<enter>.

get line count of a file

# input: file name
# output: line numbers in variable $lines
getLineCount() {
   theFile=$1

   if test ! -f $theFile ; then
      lines=0
      return
   fi

   lines=`wc -l $theFile | tr -s ' ' | cut -d ' ' -f 2`
}

log for shell


# log  

log() {
   if test $# != 2 ; then
      echo "ERROR: log() takes 2 parameters:  ."
      exit 1
   fi

   level=$1
   msg=$2
   timestamp=`date '+%Y-%m-%d %H:%M:%S'`
   echo "$timestamp $1 - $2"
}

process csv file

while IFS=, read var1 var2 dummy1 var3 dummy2 var4 ; do
   # process variables retrieved. following is just an example
   echo "$var1;$var2;$var3;$var4"
done < the_file.csv

put the output of a command in variable, and preserve line breaks

text="aaa\nbbb\n"
text="$text$(the_command)"
echo -e "$text"

Note that the '-e' switch in echo command is to make the '\n' in $text work; the quotation marks are used to preserve the line breaks in the command output.

show all processes in a friendly way

# basically all processes are supposed to start on a daily basis. when not for some reason, without 
#   this squeeze treatment, it screws up...
squeeze() {
   $str=$1

   months=$(echo 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' | tr ' ' '\n')

   for m in $months ; do
      str=$(echo $str | sed "s/$m /$m/")
   done

   echo $str
}

printHeader() {
   echo -e "pid\ttime\tprogram"
   echo '---------------------------------'
}

LC_ALL=C

export IFS='
'

myps() {
   for p in $pout ; do
      p=$(squeeze $p)
      pid=$(echo $p | cut -d ' ' -f 2)
      pt=$(echo $p | cut -d ' ' -f 9)
      param=$(echo $p | cut -d ' ' -f 12-)

      found=''

      for pInfo in $pInfoList ; do
         key=$(echo $pInfo | cut -d '|' -f 1)
         desc=$(echo $pInfo | cut -d '|' -f 2)

         if test "x$(echo $param | grep $key)" != 'x' ; then
            found='Y'
            break
         fi
      done

      if test "x$found" == 'x' ; then
         desc="UNKNOWN($param)
      fi

      echo -e "$pid\t$pt\t$desc"
   done
}

pout=$(ps auxww | grep -v grep | grep the_key_word | tr ' ')

pInfoList=$(cat << END_OF_LIST
keyword1|my desc1
keyword2|my desc2
keyword3|my desc3
END_OF_LIST)

if test "x$pout" == 'x' ; then
   echo 'No running process.'
   exit 0
fi

printHeader

myps | sort -k 3