Skip to content
AgileLogics
4 min read

File and String Tests

Prerequisites: Conditionals: if and tests

Scripts constantly check whether files exist, whether a variable is empty, and so on. [[ ]] has operators for all of these.

File tests

mkdir reports
echo "data" > data.csv
touch empty.txt

[[ -e data.csv ]]  && echo "data.csv exists"
[[ -f data.csv ]]  && echo "data.csv is a regular file"
[[ -d reports ]]   && echo "reports is a directory"
[[ -s empty.txt ]] || echo "empty.txt is empty"
[[ -r data.csv ]]  && echo "data.csv is readable"
[[ -e nope.txt ]]  || echo "nope.txt doesn't exist"
data.csv exists
data.csv is a regular file
reports is a directory
empty.txt is empty
data.csv is readable
nope.txt doesn't exist
Test True if...
-e the path exists
-f it's a regular file
-d it's a directory
-s it exists and isn't empty
-r -w -x readable / writable / executable
a -nt b file a is newer than b

String tests

empty=""
name="Ada"

[[ -z $empty ]] && echo "empty is empty"
[[ -n $name ]]  && echo "name is set to '$name'"
[[ $name =~ ^[A-Z][a-z]+$ ]] && echo "name looks like a capitalized word"
empty is empty
name is set to 'Ada'
name looks like a capitalized word
  • -z — the string is empty; -n — it isn't.
  • =~ matches a regular expression (Bash only). Try patterns in the Regex Tester.

A guard at the top of a script

cat > process.sh <<'EOF'
input=$1
if [[ -z $input ]]; then
  echo "Usage: process.sh <file>" >&2
  exit 1
fi
if [[ ! -f $input ]]; then
  echo "Error: '$input' is not a file" >&2
  exit 1
fi
echo "Processing $input ($(wc -l < "$input") lines)"
EOF

printf 'a\nb\n' > list.txt
bash process.sh missing.txt
bash process.sh list.txt
Error: 'missing.txt' is not a file
Processing list.txt (2 lines)

Checking inputs first, with clear messages, makes scripts far easier to use and debug.