טיפ באש: השתמשו ב null glob כשצריך
את הלולאה הקצרה הזאת כתבתי בסקריפט בלי לחשוב יותר מדי:
#!/bin/bash -e
for json_file in /data/*
do
echo "Importing JSON file $json_file"
python import_json.py "$json_file"
echo "-- Done"
done
ולמה בלי לחשוב? כי אם הסקריפט import_json.py
ינסה לפתוח את הקובץ שהוא מקבל לקריאה, והתיקיה ריקה, אנחנו נקבל את השגיאה:
FileNotFoundError: [Errno 2] No such file or directory: '/data/*'
הסיבה לשגיאה המוזרה היא ש bash מפענח את הביטוי /data/*
להיות הטקסט הפשוט /data/*
ולא רשימת שמות הקבצים בתיקיה שם - בגלל שאין קבצים באותה תיקיה. אפשר לראות את זה בדוגמה פשוטה יותר בלי לולאה או פייתון אם פשוט נכתוב את שתי הפקודות:
# this will print all the files in /etc
$ echo /etc/*
# but this will just print "/data/*"
$ echo /data/*
הפקודה הראשונה באמת תדפיס את כל הקבצים והתיקיות מתוך /etc
, והשניה תדפיס פשוט /data/*
. כמובן שהמחרוזת שהודפסה מהפקודה השניה אינה באמת שם קובץ ולכן אי אפשר לפתוח אותה.
הדרך הכי קלה לצאת מזה היא להשתמש ב nullglob
, שזה אומר שאם הביטוי לא מתאים לכלום אז באש יחזיר מחרוזת ריקה. נסו את זה:
$ shopt -s nullglob
$ echo /data/*
והפעם לא מקבלים שום פלט. בתוך הלולאה אני מקבל בדיוק את ההתנהגות הרצויה:
#!/bin/bash -e
shopt -s nullglob
for json_file in /data/*
do
echo "Importing JSON file $json_file"
python import_json.py "$json_file"
echo "-- Done"
done
הפעם הסקריפט לא ינסה לפתוח קובץ עם השם המוזר /data*
ופשוט לא יבצע אף פעם את גוף הלולאה כי באמת אין קבצים שמתאימים לביטוי.