bash globbing filename expansion - ghdrako/doc_snipets GitHub Wiki

Globbing

File globbing supports multiple different matching mechanisms, similar to regular expressions:

  • Matching specific characters from options written inside brackets, e.g., [ab] (a or b)
  • Matching characters from a sequence written inside brackets, e.g., [0-9] to match a number character or [a-d] to match a, b, c, or d
  • Caret (^) character to negate the selection
  • Dollar sign ($) to denote the end of the name
  • Choosing between several patterns using (PATTERN|PATTERN2)

Examples

Pattern Explanation
backup-*.gzip Match all files starting with backup- that have .gzip file extension.
[ab]* Match all files that start with either a or b.
[^ab]* Match all files that don’t start with a or b.
*.??? Match all files whose file extension has exactly three characters.
`(*.??? *.??)`

The asterisk character (*) will by default not match any hidden files starting with a dot.

for file in *.jpg; do
convert "$file" "${file%.jpg}.png"
# Replaces '.jpg' extension with '.png'
done

Negation with !

rm !(*.zip) # Delete everything EXCEPT .zip files
find . -type f ! -name ".*" # # Find non-hidden files (those NOT starting with '.')

Use { } for generating several filenames.

mkdir project_{a,b,c} # Creates directories project_a, project_b, project_c
touch report_{01..05}.txt # Creates report_01.txt through report_05.txt

Case-Insensitive matching

By default, wildcard matches are case-sensitive. To get around this (use carefully!)

  • shopt Command:
shopt -s nocasematch # Turns on case-insensitive matching
shopt -u nocasematch # Turns off case-insensitive matching

Matching across Directories (Caution!)

  • Globstar (**) (Bash 4.0+) Enables recursive wildcard matching through subdirectories. Use carefully due to performance impact on large directories.
rm -rf **/temp_* # Delete all files/folders starting with "temp_" recursively

Replaces 'project_data' with 'final_data' in filenames using ${variable/text/replace}

# Renaming with Pattern Matching
for file in project_data_*.csv; do
 mv "$file" "${file/project_data/final_data}"
done

Archive a Specific Date Range

mkdir daily_backups
tar -czf "daily_backups/backup_$(date +%Y-%m-%d).tar.gz" log_2023-11-??.txt

Check integrity of backup files

for backup in *.zip; do
  if ! zip -T "$backup"; then # Check zip integrity with '-T'
    echo "WARNING: Corrupted backup found: $backup"
  fi
done