rename#
משנה את שמו של קובץ.
rename מבקש ממערכת ההפעלה לקשור מחדש את הנתיב OLDNAME ל־NEWNAME. במערכת קבצים POSIX זוהי פעולת ספרייה אטומית יחידה: לאחר שהקריאה חוזרת בהצלחה, NEWNAME מתייחס לקובץ שהיה נגיש כ־OLDNAME, ו־OLDNAME כבר אינו קיים. זהו אותו פרימיטיב שפקודת shell mv פונה אליו כאשר המקור והיעד חיים באותה מערכת קבצים.
תקציר#
rename OLDNAME, NEWNAME
מה מקבלים בחזרה#
1 בהצלחה, 0 בכישלון כש־$! מוגדר ל־errno שקריאת המערכת rename(2) הבסיסית החזירה. תמיד בדוק את ערך ההחזרה - כישלון שקט כאן משאיר את מערכת הקבצים במצב ששאר התוכנית אינה מצפה לו:
rename $tmp, $final
or die "rename $tmp -> $final failed: $!";
אטומיות וכלל אותה־מערכת־קבצים#
rename הוא אטומי רק כאשר OLDNAME ו־NEWNAME נפתרים לאותה מערכת קבצים. בתוך מערכת הקבצים הזו, שום מצב ביניים אינו נראה: תהליך אחר הקורא את הספרייה רואה או את השם הישן או את השם החדש, אף פעם לא את שניהם ואף פעם לא אף אחד. זו הסיבה שהאידיום הקנוני ״כתיבת קובץ בבטחה״ כותב לקובץ זמני באותה ספרייה ולאחר מכן עושה rename אליו למקומו:
open my $fh, ">", "$path.tmp" or die "open: $!";
print $fh $data;
close $fh or die "close: $!";
rename "$path.tmp", $path
or die "rename: $!";
בין מערכות קבצים הקריאה נכשלת עם EXDEV ("Invalid cross-device link") ושום דבר אינו זז. פקודת mv של המערכת מטשטשת זאת בכך שהיא נופלת חזרה לעתק־ואז־unlink; rename אינו עושה כך. למעבר נייד בין־התקנים, השתמש ב־move מ־File::Copy, שמבצע בעצמו את הנפילה־חזרה copy-and-unlink.
דוגמאות#
שינוי שם בתוך ספרייה:
rename "draft.txt", "final.txt"
or die "rename: $!";
החלפת קובץ אטומית - כתוב לקובץ זמני אחאי, ואז עשה rename:
my $tmp = "$path.$$.tmp";
open my $fh, ">", $tmp or die "open $tmp: $!";
print $fh $content;
close $fh or die "close $tmp: $!";
rename $tmp, $path or die "rename $tmp -> $path: $!";
זיהוי מקרה בין־התקנים ונפילה חזרה ל־File::Copy::move:
use Errno qw(EXDEV);
use File::Copy qw(move);
unless (rename $src, $dst) {
if ($! == EXDEV) {
move($src, $dst) or die "move: $!";
}
else {
die "rename: $!";
}
}
שינוי שם של כל .log בספרייה ל־.log.old:
for my $f (glob "*.log") {
rename $f, "$f.old"
or warn "rename $f: $!";
}
מקרי קצה#
NEWNAMEכבר קיים: נדרס בשקט.renameאינו שואל, מזהיר או מסרב. אם היעד הוא קובץ רגיל הוא מבוטל כחלק מהפעולה; אם הוא ספרייה הקריאה נכשלת עםENOTDIRאוEISDIRבהתאם אםOLDNAMEהוא ספרייה. כדי לקבל סמנטיקת ״סרב לדרוס״, בדוק עם-eתחילה (וקבל שהבדיקה היא race - איןrenameat2(RENAME_NOREPLACE)נייד שחשוף דרךrenameעצמו).בין־מערכות־קבצים (
EXDEV): נכשל, משאיר את שני הנתיבים שלמים. השתמש ב־File::Copy::moveכאשר היעד עשוי להיות על mount אחר.מטפלי קובץ פתוחים: ב־Linux (וב־POSIX באופן כללי) שינוי שם של קובץ שכרגע פתוח הוא תקין. מטפל הקובץ הפתוח ממשיך להצביע על אותו inode; קריאות וכתיבות עוקבות דרכו ממשיכות לעבוד. פתיחות חדשות משתמשות בשם החדש.
ספריות: שינוי שם של ספרייה מותר, אך רק כאשר
NEWNAMEאינו קיים או הוא ספרייה ריקה. הזזת ספרייה לתת־ספרייה של עצמה נכשלת עםEINVAL.הרשאות:
renameזקוק להרשאת כתיבה + הרצה על שתי ספריות־ההורה של המקור והיעד, לא על הקובץ עצמו. כישלון מופיע כ־EACCESאוEPERM.ספריות sticky־bit (
/tmp): אם להורה היעד מוגדר sticky bit, עליך להיות בעלים של או קובץ המקור או הורה היעד; אחרת הקריאה נכשלת עםEPERMגם כאשר הספרייה ניתנת לכתיבה לכולם.Symlinks:
renameפועל על הקישור עצמו, לעולם לא על היעד שלו.rename "link", "other"משנה את שם ה־symlink; הקובץ אליו הוא מצביע אינו נוגע בו.slash גורר ב־
OLDNAME: קרנלים רבים דוחים זאת עםENOTDIRכאשר המקור אינו ספרייה. אל תסתמך על כך שהתנהגות slash־גורר תהיה ניידת.rename של אותו נתיב:
rename $p, $pמצליח ואינו עושה דבר (התנהגות הנדרשת על־ידי POSIX) כל עוד$pקיים.
הבדלים מהמקור#
תאימות מלאה עם Perl 5.42 המקורי.
ראו גם#
unlink- מסיר קובץ לפי שם; המקבילה לפירוק של יצירת אחד עםrenameלמקוםlink- יוצר שם קישור־קשיח נוסף לקובץ קיים מבלי להסיר את המקורsymlink- יוצר קישור סימבולי; שים לב ש־renameעל symlink מזיז את הקישור, לא את היעד שלוFile::Copy-moveו־copyניידים שמטפלים במקרה בין־מערכות־קבצים (EXDEV) ש־renameאינו יכול$!-errnoלאחרrenameכושל; השווה מול קבועים מ־Errno(EXDEV,EACCES,ENOENT, …)