When checking directory existence in bash scripts, many developers encounter unexpected behavior with the tilde (~) character. The initial approach:
if [ ! -d "~/Desktop" ]; then
echo "DOES NOT EXIST"
exit 1;
fi
fails because bash doesn't perform tilde expansion inside quotes or when the tilde is part of a larger string. The shell literally looks for a directory named "~" (tilde character) in the current directory.
Tilde expansion occurs before variable expansion and command substitution in bash's parsing order. For proper expansion, the tilde must:
- Be unquoted
- Appear at the beginning of a word
- Not be followed immediately by alphanumeric characters or slash
For hardcoded paths:
if [ ! -d ~/Desktop ]; then
echo "Directory doesn't exist"
exit 1;
fi
For user-provided input in variables:
read -p "Provide destination directory: " DESTINATION
# Expand tilde if present at start
if [[ "$DESTINATION" = ~* ]]; then
eval "expanded_path=$DESTINATION"
else
expanded_path="$DESTINATION"
fi
if [ ! -d "$expanded_path" ]; then
echo "'$expanded_path' does not exist" >&2
exit 1;
fi
Using bash's built-in parameter expansion:
dir="${DESTINATION/#\~/$HOME}"
if [ ! -d "$dir" ]; then
# Handle missing directory
fi
Using Python as a more robust alternative:
#!/usr/bin/env python3
import os
import sys
path = os.path.expanduser(input("Enter path: "))
if not os.path.isdir(path):
sys.exit(f"Error: {path} doesn't exist")
When using eval
for path expansion (as shown earlier), always:
- Validate user input first
- Consider using more secure alternatives
- Restrict script permissions appropriately
For scripts that need to run across different Unix-like systems:
#!/bin/bash
DEFAULT_DIR="$HOME/Desktop"
if [ ! -d "${DESTINATION:-$DEFAULT_DIR}" ]; then
echo "Directory not found" >&2
exit 1
fi
When writing bash scripts, many developers encounter this frustrating scenario: a directory check with ~
mysteriously fails even when the directory exists. Here's why your check might be failing:
if [ ! -d "~/Desktop" ]; then
echo "DOES NOT EXIST"
exit 1;
fi
This happens because the tilde character doesn't expand inside quotes in bash. The shell sees the literal string "~/Desktop"
rather than expanding it to /Users/yourusername/Desktop
.
Here are several robust solutions for directory existence checks:
# Solution 1: Use $HOME variable
if [ ! -d "$HOME/Desktop" ]; then
echo "Directory doesn't exist"
fi
# Solution 2: Let bash expand tilde before quoting
dir=~/Desktop
if [ ! -d "$dir" ]; then
echo "Directory doesn't exist"
fi
# Solution 3: For user input, use eval carefully (security warning)
read -p "Enter directory: " DESTINATION
expanded_dir=$(eval echo "$DESTINATION")
if [ ! -d "$expanded_dir" ]; then
echo "Directory doesn't exist"
fi
For scripts accepting user input that might contain tildes, consider this more secure approach:
read -p "Provide the destination directory: " DESTINATION
# Expand tilde while preventing command injection
expanded_dir=${DESTINATION/#\~/$HOME}
if [ ! -d "$expanded_dir" ]; then
echo "'$DESTINATION' does not exist." >&2;
exit 1;
fi
In bash, the double bracket syntax handles tilde expansion differently:
if [[ ! -d ~/Desktop ]]; then
echo "DOES NOT EXIST"
fi
This works because [[ ]]
performs tilde expansion before the test. However, for maximum portability across shells, the $HOME
solution is preferable.
When debugging directory checks:
- Add
echo "Testing: $dir"
before your check - Use
ls -ld ~/Desktop
to verify the path - Check permissions with
stat ~/Desktop