Line 1: Line 1:
== Test ==
+
==Test==
 
{{code|test}} is a bash built-in function to add conditionals in your script. {{code|[}} is an alias of the {{code|test}} command and are analogous.
 
{{code|test}} is a bash built-in function to add conditionals in your script. {{code|[}} is an alias of the {{code|test}} command and are analogous.
  
Line 16: Line 16:
  
 
{| class="wikitable"
 
{| class="wikitable"
! width="125px" | Operator
+
! width="125px" |Operator
! Description
+
!Description
 
|-
 
|-
! {{code|-e}}
+
!{{code|-e}}
| file exists
+
|file exists
 
|
 
|
 
|-
 
|-
! {{code|-a}}
+
!{{code|-a}}
| file exists (deprecated)
+
|file exists (deprecated)
  
 
This is identical in effect to {{code|-e}}
 
This is identical in effect to {{code|-e}}
 
|-
 
|-
! {{code|-f}}
+
!{{code|-f}}
| file is a regular file (not a directory or device file)
+
|file is a regular file (not a directory or device file)
 
|-
 
|-
! {{code|-s}}
+
!{{code|-s}}
| file is not zero size
+
|file is not zero size
 
|-
 
|-
! {{code|-d}}
+
!{{code|-d}}
| file is a directory
+
|file is a directory
 
|-
 
|-
! {{code|-b}}
+
!{{code|-b}}
| file is a block device. Eg. {{code|/dev/sda}}.
+
|file is a block device. Eg. {{code|/dev/sda}}.
 
|-
 
|-
! {{code|-c}}
+
!{{code|-c}}
| file is a character device. Eg. {{code|/dev/tty0}}.
+
|file is a character device. Eg. {{code|/dev/tty0}}.
 
|-
 
|-
! {{code|-p}}
+
!{{code|-p}}
| file is a pipe. Eg. {{code|/dev/fd/0}}.
+
|file is a pipe. Eg. {{code|/dev/fd/0}}.
 
|-
 
|-
! {{code|-h}}
+
!{{code|-h}}
| file is a symbolic link
+
|file is a symbolic link
 
|-
 
|-
! {{code|-L}}
+
!{{code|-L}}
| file is a symbolic link
+
|file is a symbolic link
 
|-
 
|-
! {{code|-S}}
+
!{{code|-S}}
| file is a socket
+
|file is a socket
 
|-
 
|-
! {{code|-t}}
+
!{{code|-t}}
| file (descriptor) is associated with a terminal device
+
|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.
 
This test option may be used to check whether the stdin [ -t 0 ] or stdout [ -t 1 ] in a given script is a terminal.
 
|-
 
|-
! {{code|-r}}
+
!{{code|-r}}
| file has read permission (for the user running the test)
+
|file has read permission (for the user running the test)
 
|-
 
|-
! {{code|-w}}
+
!{{code|-w}}
| file has write permission (for the user running the test)
+
|file has write permission (for the user running the test)
 
|-
 
|-
! {{code|-x}}
+
!{{code|-x}}
| file has execute permission (for the user running the test)
+
|file has execute permission (for the user running the test)
 
|-
 
|-
! {{code|-g}}
+
!{{code|-g}}
| file or directory has set-group-id (sgid) flag set
+
|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.
 
If a directory has the sgid flag set, then a file created within that directory belongs to the group that owns the directory.
 
|-
 
|-
! {{code|-u}}
+
!{{code|-u}}
| file has set-user-id (suid) flag set
+
|file has set-user-id (suid) flag set
  
 
|-
 
|-
! {{code|-k}}
+
!{{code|-k}}
| file or directory has sticky bit set
+
|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 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.
+
*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.
 
|-
 
|-
! {{code|-O}}
+
!{{code|-O}}
| you are owner of file
+
|you are owner of file
 
|-
 
|-
! {{code|-G}}
+
!{{code|-G}}
| group-id of file same as yours
+
|group-id of file same as yours
 
|-
 
|-
! {{code|-N}}
+
!{{code|-N}}
| file modified since it was last read
+
|file modified since it was last read
 
|-
 
|-
! {{code|f1 -nt f2}}
+
!{{code|f1 -nt f2}}
| file f1 is newer than f2
+
|file f1 is newer than f2
 
|-
 
|-
! {{code|f1 -ot f2}}
+
!{{code|f1 -ot f2}}
| file f1 is older than f2
+
|file f1 is older than f2
 
|-
 
|-
! {{code|f1 -ef f2}}
+
!{{code|f1 -ef f2}}
| files f1 and f2 are hard links to the same file
+
|files f1 and f2 are hard links to the same file
 
|-
 
|-
! {{code|!}}
+
!{{code|!}}
| "not" -- reverses the sense of the tests above (returns true if condition absent).
+
|"not" -- reverses the sense of the tests above (returns true if condition absent).
 
|}
 
|}
  
=== Integer ===
+
===Integer===
  
 
Integer tests, with {{code|test}} or inside single brackets.
 
Integer tests, with {{code|test}} or inside single brackets.
Line 121: Line 121:
  
 
{| class="wikitable"
 
{| class="wikitable"
! width="125px" | Operator
+
! width="125px" |Operator
! Description
+
!Description
 
|-
 
|-
! {{code|-eq}}
+
!{{code|-eq}}
| is equal to
+
|is equal to
 
|-
 
|-
 
|-
 
|-
! {{code|-ne}}
+
!{{code|-ne}}
| is not equal to
+
|is not equal to
 
|-
 
|-
! {{code|-gt}}
+
!{{code|-gt}}
| is greater than
+
|is greater than
 
|-
 
|-
! {{code|-ge}}
+
!{{code|-ge}}
| is greater than or equal to
+
|is greater than or equal to
 
|-
 
|-
! {{code|-lt}}
+
!{{code|-lt}}
| is less than
+
|is less than
 
|-
 
|-
! {{code|-le}}
+
!{{code|-le}}
| is less than or equal to
+
|is less than or equal to
 
|}
 
|}
  
Line 154: Line 154:
  
 
{| class="wikitable"
 
{| class="wikitable"
! width="125px" | Operator
+
! width="125px" |Operator
! Description
+
!Description
 
|-
 
|-
! {{code|1===}}
+
!{{code|1===}}
| is equal
+
|is equal
 
|-
 
|-
! {{code|<}}
+
!{{code|<}}
| is less than
+
|is less than
 
|-
 
|-
! {{code|1=<=}}
+
!{{code|1=<=}}
| is less than or equal to
+
|is less than or equal to
 
|-
 
|-
! {{code|>}}
+
!{{code|>}}
| is greater than
+
|is greater than
 
|-
 
|-
! {{code|1=>=}}
+
!{{code|1=>=}}
| is greater than or equal to
+
|is greater than or equal to
 
|}
 
|}
  
  
=== Strings ===
+
===Strings===
  
 
{| class="wikitable"
 
{| class="wikitable"
! width="125px" | Operator
+
! width="125px" |Operator
! Description
+
!Description
 
|-
 
|-
! {{code|-z}}
+
!{{code|-z}}
| string is null, that is, has zero length
+
|string is null, that is, has zero length
 
|-
 
|-
! {{code|-n}}
+
!{{code|-n}}
| string is not null.
+
|string is not null.
 
|-
 
|-
! {{code|1==}}
+
!{{code|1==}}
| is equal to
+
|is equal to
  
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 196: Line 196:
 
}}
 
}}
 
|-
 
|-
! {{code|1===}}
+
!{{code|1===}}
| is equal to
+
|is equal to
  
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 208: Line 208:
 
This operator inside a double bracket {{code|[[ ]]}} construct does pattern matching.
 
This operator inside a double bracket {{code|[[ ]]}} construct does pattern matching.
 
|-
 
|-
! {{code|1=!=}}
+
!{{code|1=!=}}
| is not equal to
+
|is not equal to
  
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 219: Line 219:
 
This operator inside a double bracket {{code|[[ ]]}} construct does pattern matching.
 
This operator inside a double bracket {{code|[[ ]]}} construct does pattern matching.
 
|-
 
|-
! {{code|1==~}}
+
!{{code|1==~}}
| Match using regex
+
|Match using regex
  
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 233: Line 233:
 
|}
 
|}
  
== Useful Functions / Utilities ==
+
==Useful Functions / Utilities==
 
Here are some common functions I use in my scripts.
 
Here are some common functions I use in my scripts.
  
=== Prompt ===
+
===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.
 
You can prompt the user for an yes or no answer using this function. An optional default values are accepted as the second argument.
  
Line 252: Line 252:
 
<phorkie>https://phorkie.leo.home.steamr.com/13/embed</phorkie>
 
<phorkie>https://phorkie.leo.home.steamr.com/13/embed</phorkie>
  
=== max ===
+
===max===
 
Find the maximum of two numbers:
 
Find the maximum of two numbers:
  
Line 260: Line 260:
 
         B=$2
 
         B=$2
 
         echo $((A>B ? A : B))
 
         echo $((A>B ? A : B))
}
+
<nowiki>}</nowiki>
 
}}
 
}}
  
=== die ===
+
===die===
 
Similar to the {{code|die}} command in PHP which prints out a message before stopping execution.
 
Similar to the {{code|die}} command in PHP which prints out a message before stopping execution.
  
Line 276: Line 276:
 
{{Info|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.}}
 
{{Info|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 ===
+
===Indent===
 
Indents text piped to the function.
 
Indents text piped to the function.
  
Line 292: Line 292:
 
}}
 
}}
  
=== Extracting / Parsing Filenames ===
+
===Extracting / Parsing Filenames===
 
Use the {{code|basename}} to extract filenames from a path and and {{code|dirname}} to extract the path of a filename.
 
Use the {{code|basename}} to extract filenames from a path and and {{code|dirname}} to extract the path of a filename.
  
Line 314: Line 314:
 
}}
 
}}
  
=== Skipping N Lines ===
+
===Skipping N Lines===
 
Use {{code|tail}} to skip the first N lines:
 
Use {{code|tail}} to skip the first N lines:
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 328: Line 328:
 
}}
 
}}
  
=== File Modification ===
+
===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.
 
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.
  
Line 337: Line 337:
 
}}
 
}}
  
== Command Substitution ==
+
=== Get Unix Timestamp ===
 +
{{Highlight
 +
| code = $ date +"%s"
 +
1596137957
 +
| lang = terminal
 +
}}
 +
 
 +
=== Get a specific column ===
 +
You can use either awk or col:
 +
{{Highlight
 +
| code = $ echo a b c {{!}} awk '{print $2}'
 +
b
 +
| lang = terminal
 +
}}
 +
 
 +
=== Get a specific section of each line ===
 +
{{Highlight
 +
| code = $ echo hello {{!}} cut -c -2
 +
he
 +
| lang = terminal
 +
}}
 +
 
 +
==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 {{code|`command`}} or the POSIX compatible form {{code|$(command)}}.
 
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 {{code|`command`}} or the POSIX compatible form {{code|$(command)}}.
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 347: Line 369:
 
Do not confuse {{code|$(command)}} with {{code|$((expression))}} which is used for arithmetic expansion.
 
Do not confuse {{code|$(command)}} with {{code|$((expression))}} which is used for arithmetic expansion.
  
=== Nested Substitution ===
+
===Nested Substitution===
 
If you are trying to do something similar to:
 
If you are trying to do something similar to:
 
{{highlight|lang=bash|code=
 
{{highlight|lang=bash|code=
Line 359: Line 381:
  
  
== Arithmetic Operations ==
+
==Arithmetic Operations==
 
Do integer arithmetic operations on variables within double brackets. For example:
 
Do integer arithmetic operations on variables within double brackets. For example:
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
Line 373: Line 395:
 
  ^ (XOR)  | (OR)  & (AND)
 
  ^ (XOR)  | (OR)  & (AND)
  
== Control Blocks ==
+
==Control Blocks==
=== Switch ===
+
===Switch===
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
 
read -p "What do you want to do?: " Option
 
read -p "What do you want to do?: " Option
Line 392: Line 414:
 
}}
 
}}
  
== Snippets ==
+
==Snippets==
=== Get First IP Address ===
+
===Get First IP Address===
 
{{highlight|lang=terminal|code=
 
{{highlight|lang=terminal|code=
 
<nowiki>
 
<nowiki>
Line 400: Line 422:
 
}}
 
}}
  
=== Run Script within Script Directory ===
+
===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.
 
For scripts that need to be running on the same directory as the script location, add this line to the top of the script.
  
Line 408: Line 430:
 
}}
 
}}
  
== See Also ==
+
==See Also==
* https://www.tldp.org/LDP/abs/html/comparison-ops.html
+
 
 +
*https://www.tldp.org/LDP/abs/html/comparison-ops.html
 
*http://sipb.mit.edu/doc/safe-shell/
 
*http://sipb.mit.edu/doc/safe-shell/
 
*http://mywiki.wooledge.org/BashFAQ
 
*http://mywiki.wooledge.org/BashFAQ
  
{{Navbox Linux}}[[Category:Linux]]
+
{{Navbox Linux}}
 +
[[Category:Linux]]

Latest revision as of 14:31, 30 July 2020

Test[edit | edit source]

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[edit | edit source]

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[edit | edit source]

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[edit | edit source]

Here are some common functions I use in my scripts.

Prompt[edit | edit source]

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[edit | edit source]

Find the maximum of two numbers:

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

die[edit | edit source]

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[edit | edit source]

Indents text piped to the function.

# Supports up to 10 tabs
function Indent (){
	Tabs="\t\t\t\t\t\t\t\t\t\t"
	sed "s/^/${Tabs:0:$((2*$1))}/g"
}

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

Extracting / Parsing Filenames[edit | edit source]

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[edit | edit source]

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[edit | edit source]

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

Get Unix Timestamp[edit | edit source]

$ date +"%s"
1596137957

Get a specific column[edit | edit source]

You can use either awk or col:

$ echo a b c | awk '{print $2}'
b

Get a specific section of each line[edit | edit source]

$ echo hello | cut -c -2
he

Command Substitution[edit | edit source]

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[edit | edit source]

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[edit | edit source]

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[edit | edit source]

Switch[edit | edit source]

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[edit | edit source]

Get First IP Address[edit | edit source]

# 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[edit | edit source]

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[edit | edit source]