Logic
#!/bin/bash
# help test for list of options
ExampleGroup 'file tests'
Example '[[ ... ]] if ... then '
file_test() {
if [[ -a /etc/passwd ]]
then
echo "file exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "file exists"
End
Example '-a same as -e file exists'
file_test() {
[[ -a /etc/passwd ]] && echo "file exists" || echo "no file"
}
When call file_test
The output should eq "file exists"
End
Example 'file is a block device (eg hard-drive or storage0)'
file_test() {
[[ -b /dev/nvme0n1p3 ]] && echo "block device" || echo "no file"
}
When call file_test
The output should eq "block device"
End
Example 'file is a character device (eg mouse, null)'
file_test() {
[[ -c /dev/null ]] && echo "character device" || echo "no file"
}
When call file_test
The output should eq "character device"
End
Example 'is a directory and exists'
directory_test() {
if [[ -d /etc ]]
then
echo "directory exists"
else
echo "no directory"
fi
}
When call directory_test
The output should eq "directory exists"
End
Example '-e file exists'
file_test() {
if [[ -e /etc/passwd ]]
then
echo "file exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "file exists"
End
Example 'regular file exists'
file_test() {
if [[ -f /etc/passwd ]]
then
echo "regular file exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "regular file exists"
End
Example '-h same as -L symlink exists'
file_test() {
if [[ -h /dev/stdout ]]
then
echo "symlink exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "symlink exists"
End
Example 'directory has sticky bit set'
file_test() {
if [[ -k /tmp ]]
then
echo "sticky bit set"
else
echo "no sticky bit"
fi
}
When call file_test
The output should eq "sticky bit set"
End
Example '-L symlink exists'
file_test() {
if [[ -L /dev/stdout ]]
then
echo "symlink exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "symlink exists"
End
Example 'file is a named pipe'
file_test() {
if [[ -p /var/run/dmeventd-client ]]
then
echo "named pipe"
else
echo "no file"
fi
}
When call file_test
The output should eq "named pipe"
End
Example 'file exists and is not empty'
file_test() {
if [[ -s /etc/passwd ]]
then
echo "file exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "file exists"
End
Example '-S socket exists'
file_test() {
if [[ -S /run/dbus/system_bus_socket ]]
then
echo "socket exists"
else
echo "no file"
fi
}
When call file_test
The output should eq "socket exists"
End
End
Whenever you’re making a Bash script, you should always use
[[
rather than[
. — BashGuide
Predicates (aka boolean functions, conditionals, tests…) are generally within double square brackets [[...]]
for text or double round brackets ((...))
for arithmetic. Historically they were within single brackets, and the double bracket notation comes from the Korn shell.
A key advantage of double square brackets is they support regex patterns using string =~ regex
, and confusingly the syntax isn’t the same as Bash globbing. The manual has the details in the conditiional constructs section.
Whereas double quoting left-hand-side variables was required by [
and isn’t assuming there are no spaces in [[
, it’s a good habit to double quote both sides.
Both the single and double bracketed tests support numerous flags to check if files exist, are empty and the same for strings and variables. The manual contains the full list in its conditional expressions section.
Pitfalls with [[...]]
- Arrays implicitly concatenate in
[[ ]]
. Use a loop (or explicit * instead of @). SC2199 - Brace expansion doesn’t happen in
[[ ]]
. Use a loop. SC2201 - Globs are ignored in
[[ ]]
except right of =/!=. Use a loop. SC2203
An if can test any command, not just conditions enclosed within brackets. — Test Constructs of Advanced Bash-Scripting Guide.
if…then is just and
Bash is prologish in that the return status of functions can often be used navigate without if predicate; then ... fi
:
if [[ -z $var ]]; then continue; fi
can be simplified to:
[[ -z $var ]] && continue