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

opendir#

פתיחת ספרייה לקריאה.

opendir מצמיד את DIRHANDLE לספרייה הקרויה ב־EXPR כך שניתן לקרוא את רשומות הספרייה עם readdir ולתפעל את המיקום עם telldir, seekdir ו־rewinddir. כאשר סיימתם, closedir משחרר את המטפל. DIRHANDLE חי במרחב שמות מובחן ממטפלי קובץ - bareword שכבר השתמשתם בו עם open פנוי לשימוש חוזר כאן, ולהיפך.

תקציר#

opendir DIRHANDLE, EXPR
opendir my $dh, EXPR

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

1 בהצלחה, 0 בכשל. בכשל $! מחזיק את הסיבה - הספרייה אינה קיימת, אינה ספרייה, אינה ניתנת לקריאה, או שהתהליך הגיע למגבלת הקבצים הפתוחים שלו. תמיד בדקו את ההחזרה; כשל שקט כאן הופך ל־readdir ריק מסתורי בהמשך.

opendir my $dh, $path
    or die "opendir $path: $!";

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

  • $! - נקבע למחרוזת שגיאת המערכת בכשל, נשאר ללא שינוי בהצלחה. תפסו אותו לפני שכל קריאת מערכת אחרת תפריע לו.

סמנטיקת מטפלים#

שלוש צורות של DIRHANDLE מתקבלות, והבחירה משנה:

  • Bareword - opendir DIR, $path יוצר dirhandle גלובלי־חבילה בשם DIR בחבילה הנוכחית. הוא נשאר פתוח עד שתסגרו אותו במפורש עם closedir או שהתוכנית תצא. הימנעו בקוד חדש; מרחב השמות הגלובלי משותף לכל החבילה.

  • סקלר לא־מוגדר - opendir my $dh, $path מבצע autovivify של $dh להפניה ל־dirhandle אנונימי רענן. כאשר $dh יוצא מהתחום וה־refcount שלו יורד לאפס, המטפל נסגר אוטומטית. זוהי הצורה לשימוש.

  • ביטוי - כל ביטוי שערכו ניתן לשימוש כ־dirhandle עקיף (בדרך כלל שם dirhandle אמיתי המוחזק במשתנה). זהות המטפל באה מערך הביטוי, לא מצורתו התחבירית.

Dirhandles ומטפלי קובץ חולקים את אותו עצם I/O בסיסי: עצם נתון יכול להיות פתוח כאחד או כאחר בכל פעם, אף פעם לא כשניהם. העברת dirhandle ל־read או מטפל קובץ ל־readdir היא שגיאת שימוש, לא קריאה שקטה של אפס בתים.

דוגמאות#

הניב הקנוני של opendir / readdir / closedir:

opendir my $dh, $dir
    or die "opendir $dir: $!";
while (my $entry = readdir $dh) {
    next if $entry eq '.' or $entry eq '..';
    print "$dir/$entry\n";
}
closedir $dh;

קריאת כל רשומה לרשימה בפעם אחת. readdir בהקשר רשימה מחזיר את כל הרשומות הנותרות:

opendir my $dh, '.' or die "opendir .: $!";
my @entries = grep { !/^\.\.?\z/ } readdir $dh;
closedir $dh;

הסתמכות על תיחום לקסיקלי לניקוי - לא נדרש closedir מפורש:

sub list_dir {
    my ($path) = @_;
    opendir my $dh, $path or return;
    return grep { !/^\.\.?\z/ } readdir $dh;
    # $dh goes out of scope here, handle is closed
}

טיפול בספרייה חסרה־או־לא־קריאה מבלי למות:

if (opendir my $dh, $path) {
    while (defined(my $e = readdir $dh)) { ... }
    closedir $dh;
} else {
    warn "skipping $path: $!";
}

חזרה לתחילת ספרייה עם rewinddir במקום פתיחה מחדש:

opendir my $dh, $dir or die $!;
my @first_pass  = readdir $dh;
rewinddir $dh;
my @second_pass = readdir $dh;
closedir $dh;

מקרי קצה#

  • כשל קובע את $!, לא את $@. opendir מדווח דרך $! כמו שאר משפחת ה־I/O; $@ נשאר ללא שינוי.

  • שימוש חוזר ב־dirhandle פתוח. opendir על מטפל שכבר פתוח סוגר בשקט את הספרייה הישנה לפני פתיחת החדשה. העדיפו closedir מפורש כאשר הקוד אמור להיות קריא.

  • נתיבים יחסיים. EXPR נפתר מול ספריית העבודה הנוכחית ברגע הקריאה. אם תבצעו chdir מאוחר יותר, נתיב יחסי שלכדתם מוקדם יותר עלול לא לציין יותר את אותו דבר - ה־dirhandle שכבר נפתח ממשיך להצביע על ה־inode הנכון ללא קשר.

  • Symlinks. opendir עוקב אחר symlinks כברירת מחדל: פתיחת קישור לספרייה פותחת את היעד. הרשומות המוחזרות על־ידי readdir הן רשומות היעד, לא הקישור.

  • Bareword לעומת אורך חיים לקסיקלי. dirhandle של bareword הוא גלובלי ומאריך חיים מעבר לבלוק העוטף; my $dh לקסיקלי מתנקה כאשר התחום מסתיים. ערבוב השניים בטעות (opendir DH, $path בתוך תת־שגרה) מדליף dirhandles בקריאות חוזרות.

  • בלבול בין מטפל קובץ למטפל ספרייה. לא ניתן לעשות print ל־dirhandle וגם לא readdir ממטפל קובץ. השגיאה צפה בקריאה המאוחרת, לא ב־opendir.

  • glob לעומת opendir. glob מרחיב תבניות בסגנון shell ומחזיר נתיבים; opendir מונה רשומות ספרייה גולמיות (כולל . ו־..) ללא פירוש. השתמשו ב־glob כאשר אתם רוצים התאמת תבניות; השתמשו ב־opendir כאשר אתם רוצים כל רשומה בדיוק כפי שמערכת הקבצים מאחסנת אותה.

הבדלים מ־upstream#

תואם מלא ל־upstream Perl 5.42.

ראו גם#

  • readdir - קריאת הרשומה הבאה (או כל הרשומות הנותרות) מ־dirhandle שנפתח עם opendir

  • closedir - שחרור dirhandle; מובלע כאשר $dh לקסיקלי יוצא מהתחום

  • rewinddir - איפוס מיקום הקריאה להתחלה ללא פתיחה מחדש

  • seekdir - מיקום מחדש של ה־dirhandle לטוקן שהוחזר קודם על־ידי telldir

  • telldir - מיקום הקריאה הנוכחי כטוקן אטום המתאים ל־seekdir

  • glob - חלופה מבוססת־תבניות כאשר אתם רוצים הרחבת שם קובץ בסגנון shell במקום מנייה גולמית של ספרייה