Filehandles, αρχεία, κατάλογοι
rename#
Αλλάζει το όνομα ενός αρχείου.
Η rename ζητά από το λειτουργικό σύστημα να επαναδέσει τη διαδρομή OLDNAME στο NEWNAME. Σε ένα σύστημα αρχείων POSIX αυτή είναι μια μοναδική ατομική λειτουργία καταλόγου: αφού επιστρέψει με επιτυχία η κλήση, το NEWNAME παραπέμπει στο αρχείο που πριν ήταν προσπελάσιμο ως OLDNAME, και το OLDNAME δεν υπάρχει πλέον. Είναι η ίδια πρωτογενής λειτουργία που χρησιμοποιεί η εντολή κελύφους mv όταν πηγή και προορισμός βρίσκονται στο ίδιο σύστημα αρχείων.
Σύνοψη#
rename OLDNAME, NEWNAME
Τι επιστρέφεται#
1 σε επιτυχία, 0 σε αποτυχία με την $! ορισμένη στο errno που επέστρεψε η υποκείμενη κλήση συστήματος rename(2). Ελέγχετε πάντα την τιμή επιστροφής - μια σιωπηρή αποτυχία εδώ αφήνει το σύστημα αρχείων σε κατάσταση που το υπόλοιπο πρόγραμμα δεν αναμένει:
rename $tmp, $final
or die "rename $tmp -> $final failed: $!";
Ατομικότητα και ο κανόνας του ίδιου συστήματος αρχείων#
Η rename είναι ατομική μόνο όταν τα OLDNAME και NEWNAME επιλύονται στο ίδιο σύστημα αρχείων. Μέσα σε αυτό το σύστημα αρχείων, καμία ενδιάμεση κατάσταση δεν είναι ποτέ ορατή: μια άλλη διεργασία που διαβάζει τον κατάλογο βλέπει είτε το παλιό όνομα είτε το νέο, ποτέ και τα δύο και ποτέ κανένα από τα δύο. Γι” αυτό η κανονική ιδιωματική φράση «γράψε ένα αρχείο με ασφάλεια» γράφει σε προσωρινό αρχείο στον ίδιο κατάλογο και μετά το μετονομάζει στη θέση του:
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 καλύπτει αυτό υποχωρώντας σε copy-then-unlink· η rename όχι. Για φορητή διασυσκευική μετακίνηση, χρησιμοποιήστε move από το File::Copy, που εκτελεί η ίδια την υποχώρηση αντιγραφή-και-unlink.
Παραδείγματα#
Μετονομασία μέσα σε κατάλογο:
rename "draft.txt", "final.txt"
or die "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(και αποδεχθείτε ότι ο έλεγχος είναι επιρρεπής σε κούρσα - δεν υπάρχει φορητήrenameat2(RENAME_NOREPLACE)εκτιθέμενη μέσω της ίδιας τηςrename).Διασυστηματική (
EXDEV): αποτυγχάνει, αφήνει αμφότερες τις διαδρομές άθικτες. ΧρησιμοποιήστεFile::Copy::moveόταν ο προορισμός μπορεί να βρίσκεται σε άλλο mount.Ανοιχτά filehandles: στο Linux (και στο POSIX γενικά) η μετονομασία αρχείου που είναι τη στιγμή εκείνη ανοιχτό είναι εντάξει. Το ανοιχτό filehandle εξακολουθεί να δείχνει στο ίδιο inode· οι επόμενες αναγνώσεις και εγγραφές μέσω του continue να λειτουργούν. Νέα ανοίγματα χρησιμοποιούν το νέο όνομα.
Κατάλογοι: η μετονομασία καταλόγου επιτρέπεται, αλλά μόνο όταν το
NEWNAMEδεν υπάρχει ή είναι κενός κατάλογος. Η μετακίνηση καταλόγου σε υποκατάλογο του εαυτού του αποτυγχάνει μεEINVAL.Δικαιώματα: η
renameχρειάζεται δικαίωμα εγγραφής + εκτέλεσης τόσο στον γονικό κατάλογο της πηγής όσο και του προορισμού, όχι στο ίδιο το αρχείο. Η αποτυχία εμφανίζεται ωςEACCESήEPERM.Κατάλογοι με sticky bit (
/tmp): αν ο γονικός του προορισμού έχει το sticky bit ορισμένο, πρέπει να είστε ιδιοκτήτης είτε του αρχείου πηγής είτε του γονικού του προορισμού· αλλιώς η κλήση αποτυγχάνει μεEPERMακόμη και όταν ο κατάλογος είναι εγγράψιμος από όλους.Συμβολικοί σύνδεσμοι: η
renameδρα στον ίδιο τον σύνδεσμο, ποτέ στον στόχο του. Ηrename "link", "other"μετονομάζει τον symlink· το αρχείο στο οποίο δείχνει μένει ανέγγιχτο.Τελική πλαγιοκάθετος στο
OLDNAME: πολλοί πυρήνες το απορρίπτουν μεENOTDIRόταν η πηγή δεν είναι κατάλογος. Μη βασίζεστε στο ότι η συμπεριφορά της τελικής πλαγιοκαθέτου είναι φορητή.Μετονομασία ίδιας διαδρομής: η
rename $p, $pπετυχαίνει και δεν κάνει τίποτα (συμπεριφορά που απαιτεί το POSIX) εφόσον το$pυπάρχει.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
unlink- αφαιρεί αρχείο κατ” όνομα· το αντίστοιχο αποδόμησης για τη δημιουργία ενός μέσωrenameστη θέση τουlink- δημιουργεί επιπλέον όνομα hard-link για ένα υπάρχον αρχείο χωρίς να αφαιρέσει το αρχικόsymlink- δημιουργεί συμβολικό σύνδεσμο· σημειώστε ότι ηrenameσε symlink μετακινεί τον σύνδεσμο, όχι τον στόχο τουFile::Copy- φορητέςmoveκαιcopyπου χειρίζονται τη διασυστηματική (EXDEV) περίπτωση που ηrenameδεν μπορεί$!-errnoμετά από αποτυχημένηrename· συγκρίνετε με σταθερές από τοErrno(EXDEV,EACCES,ENOENT, …)