(2 intermediate revisions by the same user not shown)
Line 251: Line 251:
 
Source:
 
Source:
 
<phorkie>https://phorkie.leo.home.steamr.com/13/embed</phorkie>
 
<phorkie>https://phorkie.leo.home.steamr.com/13/embed</phorkie>
 +
 +
=== max ===
 +
Find the maximum of two numbers:
 +
 +
{{highlight|lang=bash|code=
 +
max (){
 +
        A=$1
 +
        B=$2
 +
        echo $((A>B ? A : B))
 +
}
 +
}}
  
 
=== die ===
 
=== die ===
Line 268: Line 279:
 
Indents text piped to the function.
 
Indents text piped to the function.
  
Source:
+
Source: (TODO: MISSING!)
 
<phorkie>https://phorkie.leo.home.steamr.com/14/embed</phorkie>
 
<phorkie>https://phorkie.leo.home.steamr.com/14/embed</phorkie>
  
Line 313: Line 324:
 
# tail -n+0   
 
# tail -n+0   
 
# tail -n+1
 
# tail -n+1
 +
}}
 +
 +
=== File Modification ===
 +
Use {{code|stat}} to find when a file was access/modified. You an obtain the timestamp as a Unix timestamp by using the {{code|-c %Y}} parameter.
 +
 +
A Unix timestamp can be converted into a human readable timestamp using {{code|awk}}:
 +
{{highlight|lang=terminal|code=
 +
$ echo 1355514777 {{!}} awk '{ print strftime("%c", $1) }'
 +
Fri 14 Dec 2012 12:52:57 PM MST
 
}}
 
}}
  

Revision as of 17:51, 14 January 2020

Test

test is a bash built-in function to add conditionals in your script. [ is an alias of the test command and are analogous.

Use the test operators listed below with test or a single bracket test condition like the following example.

$ test -e /etc/hosts && echo "File exists"
File exists

## Note that the white space around [ and ] and also the operator are required.
$ [ -e /etc/hosts ] && echo "File exists"
File exists

$ if [ -e /etc/hosts ] ; then echo "File exists" ; fi
File exists
Operator Description
-e file exists
-a file exists (deprecated)

This is identical in effect to -e

-f file is a regular file (not a directory or device file)
-s file is not zero size
-d file is a directory
-b file is a block device. Eg. /dev/sda.
-c file is a character device. Eg. /dev/tty0.
-p file is a pipe. Eg. /dev/fd/0.
-h file is a symbolic link
-L file is a symbolic link
-S file is a socket
-t file (descriptor) is associated with a terminal device

This test option may be used to check whether the stdin [ -t 0 ] or stdout [ -t 1 ] in a given script is a terminal.

-r file has read permission (for the user running the test)
-w file has write permission (for the user running the test)
-x file has execute permission (for the user running the test)
-g file or directory has set-group-id (sgid) flag set

If a directory has the sgid flag set, then a file created within that directory belongs to the group that owns the directory.

-u file has set-user-id (suid) flag set
-k file or directory has sticky bit set
  • If set on a file, that file will be kept in cache memory, for quicker access.
  • If set on a directory, it restricts write permission. Setting the sticky bit adds a t to the permissions on the file or directory listing. This restricts altering or deleting specific files in that directory to the owner of those files.
-O you are owner of file
-G group-id of file same as yours
-N file modified since it was last read
f1 -nt f2 file f1 is newer than f2
f1 -ot f2 file f1 is older than f2
f1 -ef f2 files f1 and f2 are hard links to the same file
! "not" -- reverses the sense of the tests above (returns true if condition absent).

Integer

Integer tests, with test or inside single brackets.

Eg.

$ test 2 -eq 2 && echo equal


Operator Description
-eq is equal to
-ne is not equal to
-gt is greater than
-ge is greater than or equal to
-lt is less than
-le is less than or equal to


Integer tests can aso be done inside double parentheses. Eg.

$ ((2==2)) && echo equal


Operator Description
== is equal
< is less than
<= is less than or equal to
> is greater than
>= is greater than or equal to


Strings

Operator Description
-z string is null, that is, has zero length
-n string is not null.
= is equal to
## Does not work in zsh. Works only in sh and bash.
$ if [ "$a" = "$b" ] ; then
  echo "Equal"
fi
== is equal to
## Does not work in zsh. Works only in sh and bash.
$ if [ "$a" == "$b" ] ; then
  echo "Equal"
fi

This operator inside a double bracket [[ ]] construct does pattern matching.

!= is not equal to
$ if [ "$a" != "$b" ] ; then
  echo "Not equal"
fi

This operator inside a double bracket [[ ]] construct does pattern matching.

=~ Match using regex
$ if [ zone36-ta =~ .*ta$ ] ; then
  echo "matches"
fi

$ if [ zone36-ta =~ *ta ] ; then
  echo "matches"
fi

Useful Functions / Utilities

Here are some common functions I use in my scripts.

Prompt

You can prompt the user for an yes or no answer using this function. An optional default values are accepted as the second argument.

Example Usage:

if prompt "Is this okay?" Y ; then
    echo "It's Okay!"
 fi
 if ! prompt "Is this okay?" N ; then
    echo "It's not okay!"
 fi

Source: <phorkie>https://phorkie.leo.home.steamr.com/13/embed</phorkie>

max

Find the maximum of two numbers:

max (){
        A=$1
        B=$2
        echo $((A>B ? A : B))
}

die

Similar to the die command in PHP which prints out a message before stopping execution.

Function:

function die {
	echo $@
	exit
}
Caveat when using in a subshell
This will not work inside a subshell as it will just quit the subshell rather than the script. To get around this, you may need to kill the parent PID instead.


Indent

Indents text piped to the function.

Source: (TODO: MISSING!) <phorkie>https://phorkie.leo.home.steamr.com/14/embed</phorkie>

Usage:

echo "test" | Indent
	test
echo "test" | Indent 2
		test

Extracting / Parsing Filenames

Use the basename to extract filenames from a path and and dirname to extract the path of a filename.

Eg:

$ dirname /etc/hosts
/etc
$ basename /etc/hosts
hosts

To extract only the extension or the filename without the extension, use bash's string matching or basename:

Filename=$(basename /etc/resolv.conf)
Ext="${Filename##*.}"
Name="${Filename%.*}"
Name=`basename $Filename .conf`

Skipping N Lines

Use tail to skip the first N lines:

## -n +N outputs starting on line N.
## Eg. To skip the first 2 lines, we start on line 3:
# tail -n+3

Note that the two are equivalent, because printing from line 0 will also print starting on line 1.

# tail -n+0  
# tail -n+1

File Modification

Use stat to find when a file was access/modified. You an obtain the timestamp as a Unix timestamp by using the -c %Y parameter.

A Unix timestamp can be converted into a human readable timestamp using awk:

$ echo 1355514777 | awk '{ print strftime("%c", $1) }'
Fri 14 Dec 2012 12:52:57 PM MST

Command Substitution

Command substitution allows output from a command to be substituted in place of the command itself in a script. Commands can be enclosed within backticks `command` or the POSIX compatible form $(command).

## Eg.
echo "Today is " $(date)
echo "Today is " `date`

Do not confuse $(command) with $((expression)) which is used for arithmetic expansion.

Nested Substitution

If you are trying to do something similar to:

Something=`basename `ls /home/*.txt``

You will get an error since the expansion is ambiguous. Instead, use the $(command) substitution instead:

Something=$(basename $(ls /home/*.txt))


Arithmetic Operations

Do integer arithmetic operations on variables within double brackets. For example:

Value=1
ValuePlusOne=$((Value + 1))
ValueTimes12=$((Value * 12))

The operators that are supported are:

+ - / * % 

Bitwise operators also work:

^ (XOR)   | (OR)   & (AND)

Control Blocks

Switch

read -p "What do you want to do?: " Option

case "$Option" in
	"K")
		install_new_kernel
		die "Complete!"
		;;
	"H")
		usage
		;;
	*)
		die "Stopping installation."
		;;
esac

Snippets

Get First IP Address

# ip a | /bin/grep inet | grep -v inet6 | tail -n+2 | head -n 1 | awk '{print $2}' | cut -d'/' -f1

Run Script within Script Directory

For scripts that need to be running on the same directory as the script location, add this line to the top of the script.

#!/bin/bash
cd "$(dirname "$0")"

See Also