How to perform different operations depending on the shell script name

This technique is very common. To be honest, it is more common than I initially thought, so I will show you how to create single shell script that will display, create or destroy temporary file system depending on the name used to execute it.

Standard utilities

Look at the standard utilies as many of these behave differently depending on the used executable name.

$ find {/bin,/sbin,/usr/bin,/usr/sbin} -type l -not -lname "*alternatives*" -and -not -lname "/*" -exec stat --format="%N" {} \; | sort
'/bin/bzcmp' -> 'bzdiff'
'/bin/bzegrep' -> 'bzgrep'
'/bin/bzfgrep' -> 'bzgrep'
'/bin/bzless' -> 'bzmore'
'/bin/dnsdomainname' -> 'hostname'
'/bin/domainname' -> 'hostname'
'/bin/lessfile' -> 'lesspipe'
'/bin/nisdomainname' -> 'hostname'
'/bin/rbash' -> 'bash'
'/bin/sh' -> 'dash'
'/bin/sh.distrib' -> 'dash'
'/bin/ypdomainname' -> 'hostname'
'/sbin/dmstats' -> 'dmsetup'
'/sbin/e2label' -> 'tune2fs'
'/sbin/fsck.ext2' -> 'e2fsck'
'/sbin/fsck.ext3' -> 'e2fsck'
'/sbin/fsck.ext4' -> 'e2fsck'
'/sbin/getty' -> 'agetty'
'/sbin/ifdown' -> 'ifup'
'/sbin/ifquery' -> 'ifup'
'/sbin/mkfs.ext2' -> 'mke2fs'
'/sbin/mkfs.ext3' -> 'mke2fs'
'/sbin/mkfs.ext4' -> 'mke2fs'
'/usr/bin/atq' -> 'at'
'/usr/bin/atrm' -> 'at'
'/usr/bin/captoinfo' -> 'tic'
'/usr/bin/compose' -> 'run-mailcap'
'/usr/bin/ctstat' -> 'lnstat'
'/usr/bin/edit' -> 'run-mailcap'
'/usr/bin/i386' -> 'setarch'
'/usr/bin/infotocap' -> 'tic'
'/usr/bin/lastb' -> 'last'
'/usr/bin/linux32' -> 'setarch'
'/usr/bin/linux64' -> 'setarch'
'/usr/bin/mailq' -> '../sbin/exim4'
'/usr/bin/md5sum.textutils' -> 'md5sum'
'/usr/bin/newaliases' -> '../sbin/exim4'
'/usr/bin/pkill' -> 'pgrep'
'/usr/bin/print' -> 'run-mailcap'
'/usr/bin/pstree.x11' -> 'pstree'
'/usr/bin/reset' -> 'tset'
'/usr/bin/rtstat' -> 'lnstat'
'/usr/bin/see' -> 'run-mailcap'
'/usr/bin/sg' -> 'newgrp'
'/usr/bin/slogin' -> 'ssh'
'/usr/bin/snice' -> 'skill'
'/usr/bin/sudoedit' -> 'sudo'
'/usr/bin/unxz' -> 'xz'
'/usr/bin/x86_64' -> 'setarch'
'/usr/bin/xzcat' -> 'xz'
'/usr/bin/xzcmp' -> 'xzdiff'
'/usr/bin/xzegrep' -> 'xzgrep'
'/usr/bin/xzfgrep' -> 'xzgrep'
'/usr/sbin/addgroup' -> 'adduser'
'/usr/sbin/cpgr' -> 'cppw'
'/usr/sbin/delgroup' -> 'deluser'
'/usr/sbin/exim' -> 'exim4'
'/usr/sbin/rmail' -> 'exim4'
'/usr/sbin/rsmtp' -> 'exim4'
'/usr/sbin/runq' -> 'exim4'
'/usr/sbin/sendmail' -> 'exim4'
'/usr/sbin/vigr' -> 'vipw'

Shell script

This is a shell script that will change its behaviour depending on the name it was called. Notice that the case statement is using script basename to execute different actions.

#!/bin/bash
# Perform different operation depending on the shell script name

# shell script name and real location
shell_script_name=$(basename $0)
real_shell_script_location=$(readlink -f $0)

# usage
usage() {
  echo "Usage:"
  echo " tmpfs-info"
  echo "   display information about mounted tmpfs file systems"
  echo " tmpfs-create location size"
  echo "   create tmpfs file system using provided location and size"
  echo " tmpfs-destroy location"
  echo "   destroy tmpfs file system at given location"
}

# display information
tmpfs-info() {
  mount -t tmpfs
}

# unmount tmpfs filesystem
tmpfs-destroy() {
  if [ -n "$1" ]; then
    location=$(readlink -f $1)
    mountpoint $location >/dev/null
    if [ "$?" -eq "0" ]; then
      fs=$(mount -t tmpfs | awk '$3 == "'$location'" {print $1}')   
      if [ "$fs" == "tmpfs" ]; then
        umount $location
      else
        echo "error: mountpoint is not tmpfs"
      fi
    else
      echo "error: provided location is not a mountpoint"
    fi
  else
    echo "error: missing mountpoint"
  fi      
}

# create tmpfs filesystem
tmpfs-create() {
  if [ -n "$1" ] && [ -n "$2" ]; then
    location=$(readlink -f $1)
    mountpoint $location >/dev/null
    if [ "$?" -eq "1" ]; then
      mount -t tmpfs -o size="$2" tmpfs "$location"
    else
      echo "error: provided location is already a mountpoint"
    fi
  else
    echo "error: missing mountpoint or size"
  fi      
}

# display shell script name and location
echo "Executed command $shell_script_name using $real_shell_script_location shell script"

# execute particular function depending on the shell script name
case "$shell_script_name" in
  "tmpfs-info")
    tmpfs-info
    ;;
  "tmpfs-create")
    tmpfs-create "$1" "$2"
    ;;
  "tmpfs-destroy")
    tmpfs-destroy "$1"
    ;;
  *)
    usage
    ;;
esac

Store the above-mentioned shell script as tmpfs.sh in /usr/bin directory.

Ensure that executable bit is set.

$ sudo chmod +x /usr/bin/tmpfs.sh

Create symbolic links equivalent to the actions defined inside case statement.

$ sudo ln -s /usr/bin/tmpfs.sh /usr/bin/tmpfs-create
$ sudo ln -s /usr/bin/tmpfs.sh /usr/bin/tmpfs-destroy
$ sudo ln -s /usr/bin/tmpfs.sh /usr/bin/tmpfs-info

Usage

Display usage information.

$ tmpfs.sh
Executed command tmpfs.sh using /usr/bin/tmpfs.sh shell script
Usage:
 tmpfs-info
   display information about mounted tmpfs file systems
 tmpfs-create location size
   create tmpfs file system using provided location and size
 tmpfs-destroy location
   destroy tmpfs file system at given location

List mounted tmpfs file systems.

$ tmpfs-info 
Executed command tmpfs-info using /usr/bin/tmpfs.sh shell script
none on /dev type tmpfs (rw,nodev,relatime,size=492k,mode=755,uid=100000,gid=100000)
tmpfs on /dev/lxd type tmpfs (rw,relatime,size=100k,mode=755)
tmpfs on /dev/.lxd-mounts type tmpfs (rw,relatime,size=100k,mode=711)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,uid=100000,gid=100000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755,uid=100000,gid=100000)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k,uid=100000,gid=100000)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755,uid=100000,gid=100000)
tmpfs on /var/www/tmpfs type tmpfs (rw,nosuid,nodev,noexec,relatime,size=131072k,uid=100000,gid=100000)

Create tmpfs file system.

$ mkdir tmpfs_test
$ sudo tmpfs-create tmpfs_test 128M

List mounted tmpfs file systems to check out a new one.

$ tmpfs-info 
Executed command tmpfs-info using /usr/bin/tmpfs.sh shell script
none on /dev type tmpfs (rw,nodev,relatime,size=492k,mode=755,uid=100000,gid=100000)
tmpfs on /dev/lxd type tmpfs (rw,relatime,size=100k,mode=755)
tmpfs on /dev/.lxd-mounts type tmpfs (rw,relatime,size=100k,mode=711)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,uid=100000,gid=100000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755,uid=100000,gid=100000)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k,uid=100000,gid=100000)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755,uid=100000,gid=100000)
tmpfs on /var/www/tmpfs type tmpfs (rw,nosuid,nodev,noexec,relatime,size=131072k,uid=100000,gid=100000)
tmpfs on /root/tmpfs_test type tmpfs (rw,nodev,relatime,size=131072k,uid=100000,gid=100000)

Destroy previously created tmpfs file system.

$ sudo tmpfs-destroy tmpfs_test

List mounted tmpfs file systems to verify that it was removed.

$ tmpfs-info
Executed command tmpfs-info using /usr/bin/tmpfs.sh shell script
none on /dev type tmpfs (rw,nodev,relatime,size=492k,mode=755,uid=100000,gid=100000)
tmpfs on /dev/lxd type tmpfs (rw,relatime,size=100k,mode=755)
tmpfs on /dev/.lxd-mounts type tmpfs (rw,relatime,size=100k,mode=711)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,uid=100000,gid=100000)
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755,uid=100000,gid=100000)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k,uid=100000,gid=100000)
tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755,uid=100000,gid=100000)
tmpfs on /var/www/tmpfs type tmpfs (rw,nosuid,nodev,noexec,relatime,size=131072k,uid=100000,gid=100000)

About Milosz Galazka

Milosz is a Linux Foundation Certified Engineer working for a successful Polish company as a system administrator and a long time supporter of Free Software Foundation and Debian operating system.