Search:

PmWiki

pmwiki.org

edit SideBar

Main / Scripting

Shell: #!/bin/sh

Execute arithmetic on variables by using the `expr ....` construct.
count=`expr $count + 1`

Using grep results

EXISTS=`grep "admin" "mypasswd"`
if [ -z "${EXISTS}" ]; then
   echo "nothing"
else
   echo "found it"
fi

Multiple if conditional in shell:

if [ -n "$UBI_SEQ_NUM" ] && [ "$UBI_SEQ_NUM_CNT" -eq 1 ];
then
   echo "UBI volume found";
else
   echo "Bad UBI volume Image Sequence Number";
   exit 2;
fi

Can you do this?

if [ -n $VAR ] 

NOOOOOOOOOOOOOOO - you must have quotes!!

Arguments to a function

You can access those with $@, it's an array.

http://www.dreamsyssoft.com/unix-shell-scripting/tutorial.php

Why am I getting "Unexpected operator"?

You can't run external commands inside test brackets [] like you can in bash, so that's probably the issue. This won't work:

if [ ping ] ; then
...

Wildcard filename expansion

This is tricky to do in shell, while much easier in bash. I've only found two options. One is to remove the quotes when referencing the variable. The other is to use set:

WORKING_DIR="$BUILD_DIR/mydir-*"
set -- $WORKING_DIR 
EXPANDED_DIR="$1"

I believe one problem with this is that is overwrites the positional parameters that had arguments given to the shell script, although it's probably good practice to grab and copy any of those arguments you might need at the very beginning of the script.

Bash: #!/bin/bash

Execute arithmetic on variables by using let.

  let count+=1

To find a mother process of running scripts, use ps -ejH

To find files with a certain substring in the name: for i in *; if [[ "$i" == *letter* ]] then ...

OR
for i in * 
do
	if [[ "$i" == *@* ]]
	then
		echo $i		
	fi
done

(Add a -f check to verify it's a common file)

The count of the command line arguments can be had with $#

Arguments in an if statement

if [ "$2" = S9 ] 
then
    echo $1
fi

Getting file names

for i in $( ls . ); do
   echo item: $i
done

Assigning outputs of commands to a variable

var=$(command-name-here)
var=`command-name-here`

Using sed to alter strings in bash:
newstring= `echo "$stringvar" | sed 's/oldchars/newchars/g'

Use the % operator to erase back end of string, working right to left. Double up %% in order to work left to right, i.e. from the first occurrence on back. In this example, comma and space are the incident chars.

c=$(grep console= /proc/cmdline)
c=${c/*console=/}
c=${c%%,*}
c=${c%% *}

Writing to file within the script

This option works if EOF is left-aligned or only has tab indents in front of it.

cat <<-EOF > foo.cfg
[foofile] 
bar=100
EOF

This option works by removing the extraneous spaces with tr.

printf " \
   [foofile] 
   bar=100
" | tr -d ' ' > foo.cfg

Insert a header at the top of all files of a certain extension (MATLAB target example)

STR1="%%"
STR2="% @file"
STR3="%"
STR4="% @brief <add short description>"
STR5="% @copyright Copyright"

for filepath in `find . -name "*.m"`
do
  filename=`basename $filepath` 
  sed -i "1i $STR1\n$STR2 $filename\n$STR3\n$STR4\n$STR3\n$STR5\n$STR3\n" $filepath
done

This can be done with xargs too, but maintains the entire file path:

STR1="%%"
STR2="% @file"
STR3="%"
STR4="% @brief <add short description>"
STR5="% @copyright Copyright"

find . -name "*.m" | xargs -I ? sh -c \
                           "sed -i '1i $STR1\n$STR2 ?\n$STR3\n$STR4\n$STR3\n$STR5\n$STR3\n' ?"

Command termination

";" and "&" are command terminators, meaning fg and bg respectively, so if you write "cd & ;" having the two together is redundant and will result in an error because bash does not allow empty commands.

Multiple conditionals in one statement

if [ -n "$FOO_BAR" ] && [ "$(echo $FOO_BAR | wc -w)" -eq "1" ]
then
   echo "GOOD"
else
   echo "BAD"
   exit 2
fi

String manipulation

stringZ=abcABC123ABCabc

echo ${#stringZ}                 # 15
echo `expr length $stringZ`      # 15
echo `expr "$stringZ" : '.*'`    # 15
echo ${stringZ#*123}             # everything after '123'
str=${stringZ#*123}
echo $str
echo ${str%%ab*}                 # everything before 'ab'

Process respawn, with crash logging

#!/bin/bash

SIMPROG=/opt/ponderosa_sim/build/app/ponderosa_sim

until $SIMPROG; do
        EXITCODE=$?
        echo "ponderosa_sim exited unexpectedly.  Respawning..." >&2;
        echo $EXITCODE
        printf '%s crash, exit code %s\n' "$(date -u)" "$EXITCODE" >> /var/log/sim.log;
        sleep 2;
done

Alternative expression inside if statement

if [ `ping -w 1 -c 1 $gateway | grep -c ", 0%"` == "1" ]; then
        echo "$gateway is reachable"
else
        echo "$gateway is NOT reachable"
fi

What's this weird set -o errexit thing at the top of my script?

It has to do with catching errors - or even value 0 call returns. To prevent a fail and exit, you'll have to add an error handle to your commands in the script.

echo $BASE_DIR | grep -m 1 -c foobar || echo "foobar not found"
echo $BASE_DIR | grep -m 1 -c foobar || :
# the second one is to carry on and do nothing

Another variation is set -e which causes exit if there's a command that ends with non-zero status. Some recommend using trap instead. see http://mywiki.wooledge.org/BashFAQ/105

Using trap

With trap <stuff> EXIT you can identify commands or a function to run if the EXIT signal occurs.

    function finish {
      # Your cleanup code here
    }
    trap finish EXIT

or trap 'rmdir <dirIcreated>' EXIT.

File tests and comparison operators

http://blog.learningtree.com/testing-file-permissions-bash/
http://tldp.org/LDP/abs/html/comparison-ops.html

Performance

Scripts will execute faster if they can make use of built-in commands, i.e. versions of commonly used commands that the shell program itself re-implements, like echo. This is different from calling the separate system binary at /bin/echo, which would require a forking of the process.
More: http://tldp.org/LDP/abs/html/internal.html#BUILTINREF and https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html

Pattern Matching

What are the rules?
Shells by defaults use globs, which is less expansive than regex.
http://mywiki.wooledge.org/glob


Page last modified on January 10, 2023, at 11:30 AM