Register
It is currently Fri Oct 31, 2014 12:59 am

a function library


All times are UTC - 6 hours


Post new topic Reply to topic  [ 8 posts ] 
Author Message
 PostPosted: Fri Dec 02, 2005 7:24 pm   
Site Admin

Joined: Tue May 17, 2005 7:31 pm
Posts: 251
Location: Georgia
Code:
#!/bin/bash
# Author: Josh Bailey
# Email: jbsnake <at> <no spam> usalug.org
# A function/subroutine library
# A lot of these functions and subroutines I use
# in all my scripts, some I have only used once.
# This is a lot of hard work right here, so please
# don't get tempted by saying you did it yourself :)
# If you use something here (which you ofcourse are free to do)
# Please atleast give a link to www.usalug.org or www.bashscripts.org
# You don't have to mention me, just mention where you found such awesome code ;)


function notAForwardSlash
{
   if [[ ${1} != '/' ]]
        then
      return 0
        else
           return 1
        fi
}

function notADot
{
   if [[ ${1} != '.' ]]
   then
      return 0
   else
      return 1
   fi
}

function getFileName
{

# call this function like
# filename_variable=`getFileName /some/path/with/a/file.name`

   local STRING=$1
        local LENGTH=${#STRING}
   local n=0
   local FileName=""
   for ((n=0;n <= $LENGTH; n++))
        do
      local CHAR=${STRING:$n:1}
      if notAForwardSlash $CHAR
      then
         FileName=$FileName$CHAR
      else
         FileName=""
      fi
   done
   echo "FileName"
}

function getExtension
{

# call this like
# extension_variable=`getExtension /path/to/some/file.txt`
# extension_variable would be "txt" for that example
# you can also just pass it a filename
# extension_variable=`getExtension somefile.lst`
# extention_variable would be "lst" for that example
# but if you pass it a filename or path without a .
# it will return exactly what you pass it
# extension_variable=`getExtension /path/to/my/script`
# extension_variable would be "/path/to/my/script"

   local STRING="${1}"
   local LENGTH="${#STRING}"
   local n=0
   local Extension=""

   for ((n=0; n <= $LENGTH; n++))
   do
      local CHAR=${STRING:$n:1}
      if notADot $CHAR
      then
         Extension=$Extension$CHAR
      else
         Extension=""
      fi
   done
   echo "$Extension"
}

function getPath
{

# call this like
# chop_path=`getPath /path/to/something.file`
# chop_path would be populated with "/path/to/"

   # function to get only the path from a path/filename combo
   # first get the filename from $1 which is a path/filename combo
   local just_filename=`getFileName "$1"`
   
   # set the variable containing the path
   local newPath=${1:0:(${#1}-${#just_filename})}
   echo "$newPath"
}

function inStr
{

# call this function like
# instr_variable=`inStr "=" "1=2"`
# since the position of = is 1 (i.e. 0 1 2 )
# instr_variable would equal 1

        local searchFor="$1";
        local lenOf=${#searchFor};
        local searchIn="$2";
        for (( i=0; i < ${#searchIn}; i++ ))
        do
                if [[ "${searchIn:$i:$lenOf}" = "$searchFor" ]]
                then
         echo "$i"
                        return 0
                fi
        done
   echo "$i"
        return 1
}

function math
{

# call this function like
# math_variable=`math 1 + 2`
# the variable math_variable would be: 3

   local newNumber=`bc -l 2> /dev/null<< EOF
   scale = 2
   ${1} ${2} ${3}
   EOF
   `
   echo "$newNumber"
}

##################### sub routines ###########################

function isRoot
{

# call this like
# if [[ isRoot ]]
# then
#    yes the user is root
# else
#   no the user isn't root
#fi

   if [[ `id -u` = 0 ]]
   then
      return 0
   else
      return 1
   fi
}

function has_read_write_access
{

# call this like
# if [[ has_read_write_access /path/to/directory/to/check ]]
# then
#    yes they do
# else
#    no they don't
# fi

   ls ${1} > /dev/null
   if [[ $? -eq 1 ]]
   then
      return 1
   else
      touch ${1}/bob.yea\ do0d 2> /dev/null
      if [[ $? -eq 1 ]]
      then
         rm ${1}/bob.yea\ do0d 2> /dev/null
         return 1
      else
         rm ${1}/bob.yea\do0d 2> /dev/null
         return 0
      fi
      
   fi
}

function trimspaces
{

# call this like
# new_string=`trimspaces "some random text" " "`
# new_string variable would be "somerandomtext"
# new_string=`trimspaces "some_random_text" "_"`
# new_string variable would be "somerandomtest"
# new_string=`trimspaces "some random_text"
# new_string variable would be "somerandom_text" (default, if nothing is passed, to remove are spaces)


   local NewString=""
   local STRING="$1"
   local rmChar="$2"
   local CHAR=""
   local NewString=""

   if [[ $rmChar = "" ]]
   then
      rmChar=' '
   fi
   for ((i=0; i<${#STRING}; i++))
   do
      CHAR=${STRING:$i:1}
      if [[ $CHAR != $rmChar ]]
      then
         NewString=$NewString$CHAR
      fi
   done
   echo "${NewString}"
}

function fileExist
{

# call this like
# if [[ fileExist "/path/to/some/file.name" ]]
# then
#   yes it does
# else
#   no it doesn't
# fi

   if [[ -a "$1" ]]
   then
      return 0
   else
      return 1
   fi
}

function isNumeric
{

# call this like
# if [[ isNumeric <something> ]]
# then
#   yes it is
# else
#    no it's not
# fi

   local Numeric='y'
   local len=`echo ${#1}`
   local val=""
   local retval=""

   for ((i=0; i<$len; i++))
   do
      val=`echo ${1:$i:1}`
      echo $val | grep ^[0-9] > /dev/null
      retval=$?
      if [[ $retval -eq 1 ]]
      then
         if [[ $i -eq 0 && $val = '-' ]]
         then
            num="negative"
         else
            Numeric='n'
            break
         fi
      fi
   done
   if [[ $Numeric = 'y' ]]
   then
      return 0
   else
      return 1
   fi
}

function isAlpha
{

# call this like
# if [[ isAlpha <something> ]]
# then
#   yes it is
# else
#    no it's not
# fi

   local Alpha='y'
   local len=`echo ${#1}`
   local val=""
   local retval=""

   for ((i=0; i<$len; i++))
   do
      val=`echo ${1:$i:1}`
      val=`echo $val | tr [:upper:] [:lower:]`
      echo $val | grep ^[a-z] > /dev/null
      retval=$?
      if [[ $retval -eq 1 ]]
      then
         Alpha='n'
         break
      fi
   done
   if [[ $Alpha = 'y' ]]
   then
      return 0
   else
      return 1
   fi
}

function isAlphaNum
{

# call this like
# if [[ isAlphNum <something> ]]
# then
#    yes it is
# else
#    no it's not
# fi

   local AlphaNum='y'
   local len=`echo ${#1}`
   local val=""
   local retval=""

   for ((i=0; i<$len; i++))
   do
      val=`echo ${1:$i:1}`
      val=`echo $val | tr [:upper:] [:lower:]`
      echo $val | grep ^[a-z] > /dev/null
      retval=$?
      if [[ $retval -eq 1 ]]
      then
         echo $val | grep ^[0-9] > /dev/null
         retval=$?
         if [[ $retval -eq 1 ]]
         then
            AlphaNum='n'
            break
         fi
      fi
   done
   if [[ $AlphaNum = 'y' ]]
   then
      return 0
   else
      return 1
   fi
}

function initialCaps()
{

# call this like
# new_string=`initialCaps "john doe"`
# new_string variable would be "John Doe"

   local Cap=""
   local Info=""
   local Word=""
   local string="${1}"
   local cut=""

   while [ ${#1} != 0 ]
   do
      Cap=`echo ${string:0:1} | tr [:lower:] [:upper:]`
      Info=`echo -n $Cap; echo ${string:1:${#string}} | tr [:upper:] [:lower:]`
      Info=${Info}" "
      Word=${Word}${Info}
      shift 1
   done
   cut=${#Word}-1
   Word="${Word:0:${cut}}"
   echo "${Word}"
}

######## Music file format stuff #################################

function get_ogg_info
{

# call this like
# ogg_info_string=`get_ogg_info "/path/to/file.ogg"`
# ofcourse the string would have to be parsed
# it is pipe | delimited
# in order artist, title, album, genre, date, and track number
# inStr function needed; vorbiscomment (comes with oggenc)
   local turn=""
   local index=0
   local item=""
   local cartist=""
   local ctitle=""
   local calbum=""
   local cgenre=""
   local cdate=""
   local ctracknumber=""

   vorbiscomment -l "$1" > info.lst
   for turn in artist title album genre date tracknumber
   do
      tmp_comment=`grep -i "$turn" info.lst`
      item=`inStr "=" "$tmp_comment"`
      comment=${tmp_comment:${item}+1}
      ((index++))
      case $index in
      1)   cartist="$comment";
         ;;
      2)   ctitle="$comment";
         ;;
      3)   calbum="$comment";
         ;;
      4)   cgenre="$comment";
         ;;
      5)   cdate="$comment";
         ;;
      6)   ctracknumber="$comment";
         ;;
      esac
   done
   info="${cartist}|${ctitle}|${calbum}|${cgenre}|${cdate}|${ctracknumber}"
   echo "${info}"
   rm -f info.lst
}

function encode_flac2mp3
{

# call this like
# encode_flac2mp3 /path/to/source/file.flac /path/to/destination
# needs: getFileName function; flac encoder/decoder; lame

   local old_file="${1}"
   local new_dir="${2}"
   local short_filename=`getFileName "${old_file}"`
   local new_file="${short_filename:0:${#short_filename}-5}.mp3"
   
   flac -d -o - "${old_file}" | lame -b 320 -h - > "${new_dir}/${new_file}"
}

function encode_flac2ogg
{

# call this like
# encode_flac2ogg /path/to/source/file.flac /path/to/destination
# needs: getFileName function; flac encoder/decoder; oggenc

   local old_file="${1}"
   local new_dir="${2}"
   local short_filename=`getFileName "${old_file}"`
   local new_file="${short_filename:0:${#short_filename}-5}.ogg"
   ###### get artist and album before release #########
   # flac -d -o - "${old_file}" | oggenc -a "$artist" -l "$album" -t "${title}" - -o "${new_dir}/${new_file}"
   ####################################################
   local title="${short_filename:0:${#short_filename}-4}"

   flac -d -o - "${old_file}" | oggenc -t "${title}" - -o "${new_dir}/${new_file}"
}



function encode_ogg2mp3
{

# call this like
# encode_ogg2mp3 /path/to/source/file.flac /path/to/destination
# needs: getFileName function; oggdec; lame

   local old_file="${1}"
   local new_dir="${2}"
   local short_filename=`getFileName "${old_file}"`
   local new_file="${short_filename:0:${#short_filename}-4}.mp3"
   local info_string=`get_ogg_info "$old_file"`
   local cartist=`cut -d| -f1 ${info_string}`
   local ctitle=`cut -d| -f2 ${info_string}`
   local calbum=`cut -d| -f3 ${info_string}`
   local cgenre=`cut -d| -f4 ${info_string}`
   local cdate=`cut -d| -f5 ${info_string}`
   local ctracknumber=`cut -d| -f6 ${info_string}`

   oggdec "${old_file}" -o - | lame  -b 320 --tt "$ctitle" --ta "$cartist" --tl "$calbum" --ty $cdate --tn $ctracknumber --tg "$cgenre" -h - > "${new_dir}/${new_file}"
   sleep .5
}

####################################################################################

############################ gpg stuff #############################################

function list_private_keys
{

# call this like
# list_private_keys
# it just clears the screen then
# pipes the private items on your keyring to less

   clear;
   echo ":: Listing private keys";
   gpg --list-secret-keys | less;
   echo ":: Done";
}

function list_public_keys
{

# call this like
# list_public_keys
# it just clears the screen then
# pipes the public imported keys on
# your keyring to less

   clear;
   echo ":: Listing public keys";
   gpg --list-keys | less;
   echo ":: Done";
}
   

function decrypt_any_file
{

# call this like
# decrypt_any_file /path/to/some/encrypted/file.asc
# it clears the screen then prompts you for your passphrase
# then decrypts the encrypted file into another file

   local filename="$1";
   local person=`whoami`;
   clear;
   if [[ ${filename:${#filename}-11:11} -eq "-encrypted" ]]
   then
      local newfilename="${filename:0:${#filename}-${#person}-12}";
      gpg -d --output "$newfilename" "$filename";
      echo ":: Decrypted $filename";
      echo ":: Saved as $newfilename";
   else
      gpg -d --output "$filename.decrypted" "$filename";
      echo ":: Decrypted $filename";
      echo ":: Saved as $filename.decrypted";
   fi
}

function encrypt_any_file
{

# call this like
# encrypt_any_file /path/to/file/to/encrypt.asc "who it's encrypted for"
# it clears the screen then encrypts the file you specified
# saving the encrypted file to have the persons name and "-encrypted" at the end

   local filename="$1";
   local person="$2";
   clear;
   gpg -sea --output "$filename"."$person"-encrypted --recipient "$person";
   echo ":: File $filename encrypted";
   echo ":: Encrypted file saved as $filename.$person-encrypted";
}

function export_public_key
{

# call this like
# export_public_key "Key Identifier"
# generates a key pair and saves the public key as "Key Identifier.pub"

   local ID="$1";
   gpg -ao $ID.pub --export $ID;
   echo ":: Public Key for $ID has been generated"
   echo ":: File is saved as $ID.pub"
}

function import_public_directory
{

# call this like
# import_public_directory /path/to/directory/full/of/public/keys
# changes directory to the public key directory and imports every file there
# then goes back to the directory you started in

   local DIR=$1;
   cd "$DIR";
   for filename in *
   do
      gpg --import "$filename";
   done;
   cd ~-;
}

function create_encrypted_ascii_file
{

# call this like
# create_encrypted_ascii_file /path/to/location/for/future/message.asc "Who to encrypt for"
# opens a vi session (note you can make the editor whatever you want by changing the variable)
# once you close the editor, the file you just edited is encrypted
# then it's echo'd to the console for easy copy and pasting

   local editor="vi"
   local file="${1}";
   local person="${2}";
   ${editor} "${file}";
   gpg -sea --output "${file}.${person}-encrypted" --recipient "${person}" "${file}";
   clear;
   echo ":: Encrypted file created";
   echo ":: File saved as ${file}.${person}-encrypted";
   echo ":: Contents of file shown below";
   echo -e "\n\n";
   cat "${file}.${person}-encrypted"
}

function import_public_key
{

# call this like
# import_public_key
# it prompts you for the key-file you wish to import

   read -p "Please type the path of the public key you wish to import: " file
   if [[ -e "$file" ]]
   then
      gpg --import "$file"
   else
      echo "${file}: doesn't exist, or you typed the wrong path!"
      exit
   fi
}

function create_user_list
{

# call this like
# create_user_list
# makes a list of users on the system
# it grabs the contents of /etc/passwd
# then removes the entry for root
# and saves the list as users.list

   cat /etc/passwd | cut -d: -f1 > pre.list;
   cat pre.list | grep -v "root" > users.list;
   rm pre.list;
}
#####################################################################################3


function app_up
{

# call this like
# app_up /path/to/file/append.from /path/to/file/append.to
# puts data from a file at the top of another file instead of the bottom

   if [[ ! -e ${2} ]]
   then
      touch ${2}
   fi

   ${1} > temp
   cat ${2} >> temp
   rm -f ${2}
   mv temp ${2}
}

function createROMISO
{

# call this like
# createROMISO /dev/cdrom /path/to/new/rom.iso

   # the command that makes an ISO from a cd/dvd
   # $1 should be the device path (/dev/cdrom)
   # $2 should be the iso path and filename
   dd if=$1 of=$2 bs=32k
}

function createDIRISO
{

# call this like
# createDIRISO /path/to/new/rom.iso /path/to/directory/you/want/to/backup

   # the command that makes an ISO from a directory
   # $1 should be the iso path and filename
   # $2 should be the directory to backup
   mkisofs -o $1 $2
}

function msg
{

# call this like
# msg "Title of Message Box"
# or
# msg "Title of Message Box" $height $width

   # function for making a messagebox
   # if it has less than two arguments
   if [[ $# < 2 ]]
   then
      # use auto-size for the messagebox
      dialog --msgbox "$1" 0 0
   else
      # use specified height and width
      dialog --msgbox "$1" $2 $3
   fi
   clear
}


Top
 Profile  
 PostPosted: Tue Nov 13, 2007 5:58 am   

Joined: Mon Nov 12, 2007 3:59 pm
Posts: 1
I wonder what license this is under. BSD? GPL? And if GPL, what version of GPL?


Top
 Profile  
 PostPosted: Tue Nov 13, 2007 12:09 pm   
Site Admin

Joined: Tue May 17, 2005 7:31 pm
Posts: 251
Location: Georgia
its not under any license... read the first sudo-paragraph of that library... basically... use it if you want... all i ask is if asked... state where you got it :wink:


Top
 Profile  
 PostPosted: Sat Jul 02, 2011 1:43 am   
User avatar

Joined: Wed Jun 08, 2011 8:27 am
Posts: 189
Location: outer Shpongolia
I had to recode that. You're not using bash(1) features at all.

Code:
getFileName() {
    # usage: getFileName <filename>
    local filename=${1##*/}
   
    echo "${filename%.*}"
}

getExtension() { echo "${1##*.}"; }  # usage: getExtension <filename>
getPath() { echo "${1%/*}"; }        # usage: getPath <filename>

inStr() {
    # usage: inStr <char> <string>
    local i
   
    for ((i = 0; i < ${#2}; i++)); do
        if [[ ${2:i:1} = $1 ]]; then
            echo "$i"
        fi
    done
}

math() {
    # usage: math <scale> <expr>
    local s=$1
   
    shift
    bc <<< "scale = $s; $@"
}

isRoot() ((! UID))                                # usage: if isRoot; then ...; fi
has_read_write_access() [[ -r $1 && -w $1 ]]      # usage: if has_read_write_access <filename>; then ...; fi
trimspaces() { echo "${1//${2:-[[:blank:]]}}"; }  # usage: trimspaces <text> [ <char> ]
fileExists() [[ -f $1 ]]                          # usage: if fileExists <filename>; then ...; fi
isNumeric() [[ $1 != *[![:digit:]]* ]]            # usage: if isNumeric <string>; then ...; fi
isAlpha() [[ $1 != *[![:alpha:]]* ]]              # usage: if isAlpha <string>; then ...; fi
isAlphNum() [[ $1 != *[![:alnum:]]* ]]            # usage: if isAlphNum <string>; then ...; fi

initialCaps() {
    # usage: initialCaps <string>
             example: initialCaps 'john doe'
    local a res i

    set -f
    a=($1)
    set +f

    for ((i = 0; i < ${#a[@]}; i++)); do
        res+="${a[i]^} "
    done

    echo "${res%[[:blank:]]}"
}

create_user_list() {
    # usage: create_user_list
    local users u

    while IFS=: read -r u _; do
        users+=("$u")
    done

    printf '%s\n' "${users[@]:1}"
}

app_up() { cat - < "$1" "$2"; }  # usage: app_up <file_to_append_from> <file_to_append_to>


I didn't recode the other functions, because they rely on external programs that may not be installed on the system being used.


Top
 Profile  
 PostPosted: Wed Mar 28, 2012 10:12 am   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
hi jsz,
fine job !
for inStr, a break would save time I suppose - and what about [[ "$string" == *"$char"* ]] ? (also valid for subString)
...
by the way, I wonder why they use the notation : [[ -z "${VAR:-}" ]] in Fedora scripts. Is there an explanation why [[ -z "$VAR" ]] would not suffice ?


Top
 Profile ICQ YIM  
 PostPosted: Wed Mar 28, 2012 11:19 am   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
sorry, for inStr I see the index was meant :(
well staying with bash is not always the best solution (bc is not bash for instance)
awk is terribly fast (try it for index (or create_user_list) for instance - about ten times faster than bash - and the gain is greater the longer the string)
it's also true for the builtin bash gsub mechanism ${var//<str1>/<str2>} : it becomes unusable for long strings (execution time grows exponentially)


Top
 Profile ICQ YIM  
 PostPosted: Sun Apr 01, 2012 5:06 pm   
User avatar

Joined: Wed Jun 08, 2011 8:27 am
Posts: 189
Location: outer Shpongolia
cfeard wrote:
by the way, I wonder why they use the notation : [[ -z "${VAR:-}" ]] in Fedora scripts.
Is there an explanation why [[ -z "$VAR" ]] would not suffice ?


It's used to avoid having an error because of the nounset feature possibly enabled. ( « help set » )
See the example below.

Code:
$ [[ -z "$x" ]] && echo x is empty
x is empty
$ set -u
$ [[ -z "$x" ]] && echo x is empty
bash4.2: x: unbound variable
$ [[ -z "${x:-}" ]] && echo x is empty
x is empty


Also, quoting the LHS in the [[ ... ]] syntax isn't needed, and you can use ! instead of -z.

________

cfeard wrote:
well staying with bash is not always the best solution (bc is not bash for instance)
awk is terribly fast (try it for index (or create_user_list) for instance - about ten times
faster than bash - and the gain is greater the longer the string)
it's also true for the builtin bash gsub mechanism ${var//<str1>/<str2>} : it becomes
unusable for long strings (execution time grows exponentially)


I agree, but it's meant to be a bash(1) library...
In my opinion, the goal is to use the fewest external programs.

I used bc(1) because it supports floating-point numbers, whereas bash(1) does not,
and cat(1) because the implementation of the task would be really too slow.


Top
 Profile  
 PostPosted: Mon Apr 02, 2012 4:22 am   

Joined: Mon Feb 16, 2009 10:07 am
Posts: 19
Location: Paris - France
Hi jsz,
thank you very much for your explanation of the "${VAR:-}" notation.
(I never use the 'set -u' bash option and ceased to use the ${VAR?} notation long ago)

Quote:
In my opinion, the goal is to use the fewest external programs


calling an external program is always a matter of time : a new process is started
and I'd love to avoid this for that reason. But if calling an external program helps me to save time,
I don't hesitate. I regret that - and do not undestand why - some bash features are so slow, as I didn't understand
why the 'toupper' 'tolower' implementation in bash came so late (I used to have it in ksh).


Top
 Profile ICQ YIM  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot] and 10 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP