קלט/פלט

readdir#

קריאת הרשומה הבאה, או כל הרשומות הנותרות, ממטפל ספריות שנפתח על־ידי opendir.

readdir הוא מקבילו הספרייתי של readline: הוא מושך שמות ממטפל ספריות בזה אחר זה בהקשר סקלר, או בבת־אחת בהקשר רשימה. המטפל חייב להיות כבר פתוח באמצעות opendir; האיטרציה מקדמת מיקום ש־rewinddir, seekdir, ו־telldir יכולים לתמרן.

תקציר#

readdir DIRHANDLE
my $name  = readdir $dh;
my @names = readdir $dh;
while (readdir $dh) { ... }     # sets $_

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

תלוי הקשר:

  • הקשר סקלר: שם הרשומה הבאה כמחרוזת, או undef כאשר הספרייה מוצתה.

  • הקשר רשימה: כל רשומה שנותרה כרשימה של מחרוזות, או הרשימה הריקה כאשר הספרייה כבר מוצתה.

הרשומות הן שמות קבצים חשופים, לא נתיבים. readdir מחזיר "foo.txt", אף פעם לא "/some/dir/foo.txt". אם מתכננים להעביר את התוצאה למבחן קובץ, open, stat, או כל קריאה אחרת שמפענחת נתיבים מול ספריית העבודה הנוכחית, הקדימו את הספרייה בעצמכם - readdir אינו מבצע chdir לספרייה שאותה הוא קורא.

הרשימה תמיד כוללת את הרשומות . (הספרייה הנוכחית) ו־.. (ספריית האב) כפי שמדווחות על־ידי מערכת הקבצים הבסיסית. סננו אותן במפורש אם אינכם רוצים אותן:

my @real = grep { $_ ne '.' && $_ ne '..' } readdir $dh;

הסדר תלוי במערכת הקבצים, ולא אלפביתי. ext4, XFS, tmpfs, NFS, ו־FAT, כל אחת מחזירה רשומות בסדר הפנימי שלה, שיכול להיות סדר הכנסה, סדר האש, או משהו אחר לגמרי. לעולם אל תניחו פלט ממוין. אם נחוץ סדר צפוי, מיינו את התוצאה:

my @names = sort readdir $dh;

דוגמאות#

קריאת כל שם לרשימה, השלכת רשומות הנקודות, ומיון:

opendir(my $dh, $some_dir) or die "opendir $some_dir: $!";
my @names = sort grep { !/^\.\.?\z/ } readdir $dh;
closedir $dh;

איטרציה רשומה אחת בכל פעם. readdir חשוף בתנאי while מציב ל־$_ ובודק את התוצאה למוגדרוּת, לא לאמיתיוּת - כך שרשומה ששמה מילולית "0" עדיין שומרת את הלולאה רצה:

opendir(my $dh, $some_dir) or die "opendir $some_dir: $!";
while (readdir $dh) {
    print "$some_dir/$_\n";
}
closedir $dh;

מבחן קובץ עם הספרייה מקודמת - שכחת הקידומת היא הבאג הקלאסי של readdir:

opendir(my $dh, $some_dir) or die "opendir $some_dir: $!";
my @dotfiles = grep { /^\./ && -f "$some_dir/$_" } readdir $dh;
closedir $dh;

הקשר סקלר - שם אחד לכל קריאה, undef מסמן סוף ספרייה:

opendir(my $dh, $some_dir) or die "opendir $some_dir: $!";
while (defined(my $name = readdir $dh)) {
    next if $name eq '.' || $name eq '..';
    process("$some_dir/$name");
}
closedir $dh;

חזרה לאחור וקריאה בפעם השנייה - המטפל נשאר פתוח וניתן לשימוש:

my @first  = readdir $dh;
rewinddir $dh;
my @second = readdir $dh;   # same entries, possibly different order

מקרי קצה#

  • מטפל מוצה: קריאות נוספות מחזירות undef בהקשר סקלר, רשימה ריקה בהקשר רשימה. השתמשו ב־rewinddir כדי להתחיל מחדש.

  • מטפל סגור או לא־תקף: מחזיר undef (סקלר) או רשימה ריקה (רשימה) ומגדיר את $!. תחת use warnings, Perl פולט readdir() attempted on invalid dirhandle.

  • מבחן מוגדרוּת ב־while: גם while (readdir $dh) וגם while (my $n = readdir $dh) (ומקבילותיהם ב־for) מטופלים במיוחד לבחינת defined, לא אמיתיוּת. רשומה ששמה "0" מוחזרת והלולאה ממשיכה.

  • . ו־.. נוכחים תמיד במערכות קבצים POSIX, גם בספרייה ריקה לחלוטין אחרת. סננו אותם אם רוצים רק תוכן אמיתי.

  • ללא קידומת נתיב: הרשומות הן שמות חשופים. כל מבחן קובץ או open על ערך ההחזרה הגולמי בודק יחסית לספריית העבודה הנוכחית, לא $some_dir.

  • אין מיון: הסדר הוא מה שהקרנל מחזיר. החילו sort במפורש אם יציבות חשובה.

  • שינויי ספרייה במקביל: רשומות שמתווספות או מוסרות במהלך איטרציה עשויות להופיע או שלא, לפי הפלטפורמה. ההנחה הבטוחה היחידה היא שרשומות שנוכחו בעת opendir ולא הוסרו ידווחו.

  • קידוד: readdir מחזיר מחרוזות בתים כפי שהקרנל מאחסן אותם. במערכת קבצים שמשתמשת בשמות קבצים UTF-8, החילו Encode::decode_utf8 או הגדירו את הפרגמה open אם נחוצות מחרוזות תווים.

הבדלים מ־upstream#

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

ראו גם#

  • opendir - פותח את מטפל הספריות ש־readdir קורא ממנו; תמיד הקריאה הראשונה ברצף

  • closedir - משחרר את המטפל לאחר שהאיטרציה הסתיימה

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

  • seekdir - קופץ למיקום שנרשם קודם לכן

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

  • glob - התאמת תבניות בסגנון shell על תוכן ספרייה; גבוה־רמה יותר כשרוצים *.txt במקום כל רשומה