Bash shell script tip: Run commands from a variable

There are many situations in which you may want to run different command in your shell script depending on requirements and circumstances. So how do you select and run a command?

ADVERTISEMENTS

The old way…

The old way is use the case statement or if..else..fi command. For example:

#!/bin/bash
if [ this -eq that ];then
   command1
else
   command2
fi

The new way…

BASH allows you to assign or store a command name in a variable. For example create a variable called CMD:

#!/bin/bash
[ this -eq that ] && CMD=”/bin/ls” || CMD="/bin/date"
$CMD

Above shell script is a simple example of this concept. CMD variable stores /bin/ls or /bin/date command. To run command you simply type a variable name. So you are using contents of a variable to run command itself depending on circumstances. For example write a backup script to backup data to tape, NAS/ftp server or using scp command. You can run a script as follows:
/path/to/backup.sh nas
/path/to/backup.sh tape
/path/to/backup.sh scp

Now depend upon circumstances you need to swap a command for backup task. Here is a sample script:

#!/bin/bash
CMD=""
DIRS="/etc /home /www /data1 /data2 /var/log /var/spool/mail"
FILE="/backup/$(hostname)-$(date +'%m-%d-%y').tar.gz"
[ "$1" == "nas" ] && CMD="lftp -u user,password -e 'cd /dump/; mput /backup/*; quit' nas.mylan.com" || :
[ "$1" == "scp" ] && CMD="scp /backup/* scponly@dumpserver:incoming' username" || :
[ "$1" == "tape" ] && CMD='tar -cf /dev/st0 /backup/*' || :
[ "$CMD" == "" ] && exit 1 || :

# make a backup
tar -zcvf  $FILE $DIRS
# Now depend upon circumstances run a backup command
$CMD

Now you can run a different backup command in your script depending on parameter passed to script itself. You can also use this trick to write a cross platform shell script.

🐧 Get the latest tutorials on SysAdmin, Linux/Unix, Open Source & DevOps topics via:
CategoryList of Unix and Linux commands
File Managementcat
FirewallCentOS 8 OpenSUSE RHEL 8 Ubuntu 16.04 Ubuntu 18.04 Ubuntu 20.04
Network Utilitiesdig host ip nmap
OpenVPNCentOS 7 CentOS 8 Debian 10 Debian 8/9 Ubuntu 18.04 Ubuntu 20.04
Package Managerapk apt
Processes Managementbg chroot cron disown fg jobs killall kill pidof pstree pwdx time
Searchinggrep whereis which
User Informationgroups id lastcomm last lid/libuser-lid logname members users whoami who w
WireGuard VPNCentOS 8 Debian 10 Firewall Ubuntu 20.04

ADVERTISEMENTS
26 comments… add one
  • Bruno Apr 24, 2007 @ 7:41

    It would be nice to write just 2 lines about the way it works : (condition-A && condition-B) : bash evaluate condition-B only if condition-A is true. If condition-A is false, the result is FALSE anyway and bash doesn’t need to evaluate condition-B. Then it goes thru all the || conditions.
    Or point to a page that explain this.
    Anyway, it is very nice to be able to read these tips on a regular basis.
    Thanks

  • Mahesh May 4, 2007 @ 6:54

    Hi

    I want to take tar-backup of user home folders on RH9 Linux.

    My short script is as follows :

    #!/bin/bash
    #pwd
    cd /home
    tar cvzf /backup/archive/usr1-`date +%C%y%m%d`.tar.gz usr1
    tar cvzf /backup/archive/usr2-`date +%C%y%m%d`.tar.gz usr2
    .
    .
    So On !!!!!!!!!

    If i am running this script from cmd , it works fine. But If i cron the job it stops aborted on 2nd directory itself with half-completed tar file.
    How to solve this problem? I am not so novice in Linux. Pls help.

    Regards /Mahesh

  • raihan Sep 22, 2007 @ 12:35

    can you guys please send me linux shell script commands for backup documents home folder, i need it
    very badly because i need to submit it on 24/9/07 to my teacher..please any one kindly send me this..
    my e-mail address raihan_alam@hotmail.com

  • corex Dec 8, 2007 @ 14:32

    I experienced another problem.
    If I call script files, input methods (read ) are ignored.

    find /media/private -iname "*.bash" | while read file
    do
    echo "Executing: $file"
    $file -m
    if [ "$?" -ne 0 ]
    then
    echo "Error executing $file"
    exit 1
    fi

    echo "done"

  • Finnbarr Murphy Mar 24, 2008 @ 10:02

    This is not just a bash feature as you imply. $CMD works with Korn shell and most other shells.

  • charusrinivasan Apr 2, 2009 @ 13:01

    hai i want a example linux program for case statement

  • pavium Apr 22, 2009 @ 13:26

    It may be slightly more clever to use variables this way, but what are we sacrificing? READABILITY.

    You’ll be sorry when to look at the script a few months from now.

  • kalem Dec 14, 2009 @ 11:30

    hi, i am trying to make a precess to run by itself whenever a media is plugged.
    the process finds and eliminate (deletes) programs ,viruses .
    since i use UNIX/lunix , these programs don’t run on my machine.
    can any one say some ?
    thanks in advance

  • Hanish May 17, 2010 @ 14:39

    if I give a PIPE to a command then it does not work like

    CMD=’ps -ef|grep vnc’

    Help me out…

  • Hanish May 17, 2010 @ 16:00

    Hi investigated and eval did a trick.

    CMD=’ps -elf|grep vnc’
    eval $CMD

    Thanks to all

  • dev May 10, 2011 @ 17:51

    Hi,

    I am trying to execute some list of commands.So,I have added my commands inside a csv file.I am trying to read that command and execute the command and store the result of the command in the variable.

    cmd=`echo $line | awk -F ‘;’ ‘{print $1}’`
    After this “cmd” gets the value like “cat filename | wc -l ”

    I am trying to store in a variable like this
    count=`$cmd`.

    Since there is a pipe i am getting error.
    Can some one help me on this

    • Rhongomiant Nov 17, 2011 @ 14:40

      dev,

      cmd=`echo $line | awk -F ‘;’ ‘{print $1}’`
      count=`$cmd`

      The variable cmd is storing the results of a command because you have the command encapsulated by backticks “. Based on this information it seems like you are doubling your work. I would modify as follows.

      cmd=`echo $line | awk -F ‘;’ ‘{print $1}’`
      count=”$cmd”

      or

      count=`echo $line | awk -F ‘;’ ‘{print $1}’`

      If you really need it setup this way, use double or single quotes to encapsulate the command defined by cmd.

      cmd=”echo $line | awk -F ‘;’ ‘{print $1}’”

      I have not had luck storing commands that contain awk in a variable and calling it later. I usually use a function.

      cmd () {
      echo $line | awk -F ‘;’ ‘{print $1}’
      }

      count=`cmd`

  • dev May 10, 2011 @ 17:58

    Hanish,

    You did a great investigation man. My problem also solved

    by giving like this count =`eval $cmd`

    Thanks a lot hanish

  • samira Oct 2, 2011 @ 18:34

    Hanish May 17, 2010
    Hi investigated and eval did a trick.

    CMD=’ps -elf|grep vnc’
    eval $CMD

    Thanks to all

    ————————–
    thankss soooo muccchhhhhhhh it is workeed

  • Petridish Jan 25, 2012 @ 15:53

    I’m a bit new to linux scripting, but I come from a programming background (c/c++). Out of curiosity, is there a different scripting language besides bash? The syntax is horrible, and I find it incredibly difficult to use.

    • Hanish Madan Apr 13, 2012 @ 7:46

      Since you are from c/c++ background try to program in CSH or TCSH shell.

  • Sanket Apr 11, 2012 @ 9:21

    Hi,

    I am trying to execute command (in ksh) stored in varialbe and want to capture output in second variable. For eg,

    var1=”ls -l $RMD_REPORTS/nat_logs/*${REPORT_DATE}*.xml 2>/dev/null | awk ‘{print $NF}'”;
    var2=`eval $var1`;
    echo $var2

    I was expecting only file names as output of above command, however “awk” filter in above command is not working and output of “echo” is same as “ls -l” command. Can anyone tell what’s wrong in above commands?

    • Rhongomiant Apr 11, 2012 @ 12:29

      Sanket,

      I believe you need to escape the $ in the awk statement, so $NF. This works for bash, but I do not know ksh.

      var1=”ls -l $RMD_REPORTS/nat_logs/*${REPORT_DATE}*.xml 2>/dev/null | awk ‘{print $NF}’”;

      • Sanket Apr 12, 2012 @ 6:31

        Thanks mate!
        Yes, it works in ksh as well. 🙂
        Sorry, but didn’t get reson why eval can’t interpret awk variable ($NF)?

        • Hanish Madan Apr 13, 2012 @ 10:52

          try below: –

          var1=”ls -l $RMD_REPORTS/nat_logs/*${REPORT_DATE}*.xml 2>/dev/null | awk ‘{print $NF}’”;

          echo $var1

    • Hanish Madan Apr 13, 2012 @ 11:02

      okay below worked for me: –

      #!/bin/ksh

      var1=”ls -l ~/|awk ‘{print $1}'”
      var2=`eval $var1`
      echo $var2

  • Lakshmi Jul 17, 2012 @ 7:13

    Any one please let me know how to call a variable of a shell script in another shell script without using export

  • Rhongomiant Jul 18, 2012 @ 4:30

    Lakshmi,

    Given the very general nature of your question, it is impossible for anyone to provide you with helpful information. We need to know what you are doing, why you can’t use export, etc. Basically you are asking how you can call someone in a different area code without entering the area code. You can’t call them, but if you use the same central repository, twitter, facebook, etc. you can share information. If you can’t use export and using the source option will not work then you need a central repository for information shared between scripts. This could be a file, a database, etc.

  • 6uru Oct 29, 2012 @ 12:45

    which shell script
    command use to run databases

  • Vinod Nov 21, 2012 @ 10:26

    If I understand your Q right, say you are executing b.sh from within a.sh and like to use the variables set in b.sh. Then you need to source b.sh from within a.sh

    #———–in a.sh —————–
    . ./b.sh
    #now all variables set in b.sh will be available here

  • Rajagopalarao G Jun 8, 2016 @ 10:19

    Hi All,

    My Condition is like below.. Could any one help on pls ?
    SEARCH=”find `pwd` -name”
    $SEARCH resources.xml | grep $SEARCH_DIR | grep $1 | grep ‘cells’
    but am not getting the pwd as i mentioned in that variable.
    pls help

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre>, <code>...</code> and <kbd>...</kbd> for code samples.