מטפלי קובץ קבצים ספריות

glob#

מרחיב תבנית שם קובץ בסגנון shell לרשימת הנתיבים התואמים.

glob לוקח מחרוזת תבנית כגון "*.c" או "src/**/*.pm" ומחזיר את שמות הקבצים על הדיסק התואמים, באותו סגנון ש־Unix shell היה מפיק. בהקשר רשימה הוא מחזיר את כל ההתאמות בבת אחת; בהקשר סקלרי הוא מתנהג כאיטרטור עם מצב, מחזיר התאמה אחת לכל קריאה ו־undef כאשר הרשימה מוצתה. ללא ארגומנט, glob מרחיב את התבנית ב־$_.

תקציר#

glob EXPR
glob
<PATTERN>

מה מקבלים בחזרה#

בהקשר רשימה, רשימה (אולי ריקה) של שמות קבצים. רשימה ריקה משמעה שהתבנית לא התאימה - זו אינה שגיאה ואינה קובעת את $!.

בהקשר סקלרי, glob הוא איטרטור: כל קריאה מחזירה את ההתאמה הבאה, ולאחר ההתאמה האחרונה קריאה נוספת מחזירה undef. מצב האיטרטור הוא לכל־אתר־קריאה, כך ששתי לולאות while (my $f = glob ...) במיקומי מקור שונים אינן מפריעות זו לזו.

my @mp3  = glob "*.mp3";            # list context
while (my $f = glob "*.mp3") { }    # scalar context, iterator

מצב גלובלי שהוא נוגע בו#

  • $_ - נקרא כאשר glob נקרא ללא ארגומנט.

  • glob עצמו אינו קובע את $! ב־״אין התאמות״. אי־התאמה היא רשימה ריקה לגיטימית, לא כשל.

  • כאשר ביטוי glob משמש כתנאי של לולאת while או for, Perl משייך באופן מובלע את התוצאה ל־$_ ובודק מוגדרוּת, לא אמת - כך ששם קובץ "0" עדיין שומר את הלולאה רצה.

הקיצור <...> וכיצד Perl בוחר בו#

<*.c> הוא תחביר חלופי ל־glob("*.c"). צורת סוגריים־משולשים חולקת reader עם <FH> (readline); המפענח מחליט באיזו מהן התכוונתם בזמן ההידור על־סמך מה שיושב בין סוגריים־המשולשים:

  • Bareword שיכולה להיות מטפל קובץ (<STDIN>, <FH>) → readline.

  • סקלר פשוט (<$fh>) → readline על אותו מטפל.

  • כל דבר הנראה כתבנית (<*.c>, <"*.txt">, <${dir}/*>) → glob.

הפונקצייה ה־named glob חד־משמעית וניתנת לחיפוש טוב יותר. העדיפו אותה בקוד חדש; פנו ל־<...> רק לתבניות הקצרות ביותר לזריקה חד־פעמית.

my @txt = <"*.txt">;                # same as glob '"*.txt"'
my @txt = glob "*.txt";             # recommended

רווחים מפצלים את התבנית#

glob מפצל את הארגומנט שלו ברווחים ומתייחס לכל סגמנט כתבנית נפרדת. התוצאות משורשרות:

my @sources = glob "*.c *.h";       # all .c OR .h files
my @all     = glob ".* *";          # every entry in cwd

כדי לבצע glob על שם קובץ שמכיל רווחים בעצמו, עטפו אותו בזוג מירכאות פנימי כדי שהפיצול יראה סגמנט אחד:

my @spacey = glob '"*e f*"';        # files with "e f" in the name
my @spacey = glob q("*e f*");       # same, q() for clarity
my @spacey = <"*e f*">;             # same via the shortcut form

שילוב משתנה לתוך תבנית עם רווחים:

my @spacey = glob "'*${var}e f*'";
my @spacey = glob qq("*${var}e f*");

אם כלל פיצול־הרווחים מפריע, השתמשו ב־bsd_glob של File::Glob ישירות - הוא לוקח את התבנית מילולית.

הרחבת סוגריים מסולסלים ללא wildcard#

אם התווים המיוחדים היחידים הם סוגריים מסולסלים לא־ריקים, glob כלל אינו נוגע במערכת הקבצים: הוא רק מונה את המכפלה הקרטזית של החלופות. הדבר שימושי ליצירת צירופי מחרוזות:

my @pairs = glob "{apple,tomato,cherry}={green,yellow,red}";
# apple=green, apple=yellow, apple=red,
# tomato=green, tomato=yellow, tomato=red,
# cherry=green, cherry=yellow, cherry=red

File::Glob - המנוע, והאפשרויות שלו#

glob ממומש על־גבי bsd_glob של File::Glob. ייבוא תגי המודול מכוון את ההתנהגות עבור יחידת ההידור כולה:

  • :nocase - התאמה ללא רגישות לאותיות גדולות וקטנות.

  • :case - אילוץ התאמה רגישה לאותיות גדולות וקטנות (ברירת המחדל ברוב מערכות הקבצים של Unix).

  • :globally - מחליף את אופרטור ה־glob הליבתי ב־bsd_glob כך שכל glob(...) ו־<...> בקובץ קולטים את האפשרויות שלכם.

use File::Glob qw(:globally :nocase);
my @txt = glob "readme*";           # README, readme.txt, Readme.md

קראו ל־bsd_glob ישירות כשצריך דגלים לכל קריאה, או כשרוצים לעקוף את כלל פיצול־הרווחים:

use File::Glob qw(bsd_glob GLOB_TILDE GLOB_BRACE);
my @files = bsd_glob("~/docs/*.{md,rst}", GLOB_TILDE | GLOB_BRACE);

דוגמאות#

לפרט כל קובץ מקור של Perl בספרייה הנוכחית:

my @perl_files = glob "*.pl *.pm";

איטרציה על קבצי MP3 אחד בכל פעם - שימושי כשהרשימה עשויה להיות גדולה ולא רוצים להממש אותה:

while (my $song = glob "*.mp3") {
    process($song);                 # one filename per iteration
}

תבניות רקורסיביות אינן מובנות; * אינו חוצה את /. סרקו את העץ עם File::Find או שלבו את glob עם מעבר מפורש:

my @all_c;
for my $dir (glob "src/*") {
    push @all_c, glob "$dir/*.c" if -d $dir;
}

השתמשו בצורת האיטרטור בתנאי while - התוצאה משוייכת ל־$_ ונבדקת למוגדרות, כך ששמות קבצים כמו "0" אינם מסיימים את הלולאה:

while (<*.log>) {
    unlink $_ if -M $_ > 30;        # older than 30 days
}

התאמה ללא רגישות לאותיות גדולות וקטנות עבור קובץ שלם:

use File::Glob qw(:globally :nocase);
my @readmes = glob "readme*";

מקרי קצה#

  • אין התאמות: מחזיר רשימה ריקה. אין אזהרה, אין קביעה של $!. אם צריך ״התבנית חייבת הייתה להתאים״, בדקו את scalar @files בעצמכם.

  • glob ללא ארגומנט: משתמש ב־$_. glob עירום בתוך while (<>) רק לעיתים נדירות הוא מה שרוצים - התבנית תהיה כל שורת קלט שזה עתה קראתם.

  • while (glob ...) משייך ל־$_ ובודק מוגדרות: שם קובץ "0" הוא שקר תחת כללי בוליאן רגילים, אבל הלולאה עדיין רצה כי התנאי הוא defined $_. הדבר תואם את הכלל עבור readline באותו מיקום.

  • Wildcards ורווחים: כלל הפיצול־ברווחים אומר ש־glob "a b" מחפש את a ואת b כשתי תבניות, לא את המחרוזת המילולית "a b". השתמשו במירכאות פנימיות או ב־bsd_glob כאשר שם הקובץ מכיל רווחים באופן לגיטימי.

  • קבצים מוסתרים: . מוביל אינו מותאם על־ידי * - יש צורך בסגמנט .* מפורש (glob ".* *") כדי לכלול dotfiles. הדבר תואם סמנטיקת shell glob, לא סמנטיקת regex.

  • הרחבת tilde: glob "~/foo" עובד כי File::Glob מרחיב ~ כברירת מחדל. כשכותבים אותו דרך bsd_glob ללא GLOB_TILDE בדגלים, מקבלים ~ מילולי.

  • שילוב בתוך <...>: <$var/*.c> משלב את $var בזמן ריצה. שימוש בצורת סוגריים־משולשים אינו פוטר אתכם מכללי המירכאות־הכפולות הרגילים של Perl.

  • עמימות סוגריים־משולשים: <FOO> היא קריאת מטפל, <$foo> היא קריאת מטפל, <*.c> הוא glob. <$foo/*.c> - סקלר אחד בתוספת תווי תבנית - הוא glob. ההכרעה היא בזמן ההידור; שינויים בזמן ריצה ל־$foo אינם מחליטים אותה מחדש.

הבדלים מהמקור#

תאימות מלאה עם Perl 5.42 המקורי.

ראו גם#

  • opendir - פותח מטפל ספרייה למעבר עדין יותר מזה שהתאמת תבניות נותנת

  • readdir - קורא רשומות ממטפל ספרייה אחת בכל פעם; שלבו עם opendir כשצריך כל רשומה (כולל אלו ש־glob מסתיר, כמו dotfiles) או מידע על טיפוס קובץ

  • readline - המשמעות האחרת של <...>; חולק את תחביר סוגריים־המשולשים אך קורא שורות ממטפל קובץ

  • File::Glob - המימוש הבסיסי; השתמשו ב־bsd_glob ישירות עבור דגלים לכל־קריאה וכדי לעקוף את כלל פיצול־הרווחים

  • $_ - מקור תבנית ברירת המחדל עבור glob עירום, והמשתנה שמשוייך באופן מובלע כאשר glob משמש כתנאי לולאת while/for