Si l'emplacement d'origine et le nouvel emplacement du fichier se trouvent sur le même système de fichiers, un "déplacement" est conceptuellement identique à un "renommer".
#include <stdio.h>
int rename (const char *oldname, const char *newname)
La manière habituelle de déplacer un fichier en C est d'utiliser rename(2), qui échoue parfois.
Si vous ne pouvez pas utiliser l'appel système rename(2) (par exemple parce que la source et la cible sont sur des systèmes de fichiers différents), vous devez interroger la taille, la permission et d'autres métadonnées du fichier source avec stat(2); copier les données en boucle sur read(2), write(2) (en utilisant un tampon de plusieurs kilo-octets), open(2), close(2) et les métadonnées en utilisant chmod(2), chown(2), utime(2) . Vous pouvez également vous soucier de copier des attributs en utilisant getxattr(2), setxattr(2), listxattr(2). Vous pouvez également dans certains cas utiliser sendfile(2), comme l'a commenté David C. Rankin.
Et si la source et la cible se trouvent sur des systèmes de fichiers différents, il n'y a aucun moyen de rendre le déplacement atomique et d'éviter les conditions de concurrence (donc utiliser rename(2) est préférable lorsque cela est possible, car il est atomique selon sa page de manuel). Le fichier source peut toujours être modifié (par un autre traitement) lors des opérations de déplacement...
Donc, un moyen pratique de déplacer des fichiers est d'essayer d'abord de faire un rename(2), et si cela échoue avec EXDEV
(lorsque ancienchemin et nouveauchemin ne sont pas sur le même système de fichiers monté), alors vous devez copier les octets et les métadonnées. Plusieurs bibliothèques fournissent des fonctions faisant cela, par ex. Qt QFile::renommer.
Lisez Advanced Linux Programming - et consultez syscalls(2) - pour en savoir plus (et essayez également de strace
quelques mv
commande pour comprendre ce qu'elle fait). Ce livre est librement et légalement téléchargeable (vous pouvez donc en trouver plusieurs exemplaires sur le Web).
Le /bin/mv
La commande (voir mv(1)) fait partie de GNU coreutils qui est un logiciel libre. Vous pouvez soit étudier son code source, soit utiliser strace(1) pour comprendre ce que fait cette commande (en termes de syscalls(2)). Dans certains shells Unix open source comme sash ou busybox, mv
pourrait être un shell intégré. Voir aussi path_resolution(7) et glob(7).
Il existe des cas subtils (imaginez un autre processus ou pthread effectuant des opérations sur les fichiers sur le même système de fichiers, répertoire ou fichiers). Lisez quelques manuels sur le système d'exploitation pour en savoir plus.
L'utilisation d'un mélange de snprintf(3), system(3), mv(1) peut être délicate si le nom du fichier contient des caractères bizarres tels que tab ou
ou saut de ligne, ou commence par un -
initial . Voir errno(3).