Se la posizione originale e quella nuova del file si trovano sullo stesso filesystem, allora uno "spostamento" è concettualmente identico a un "rinomina".
#include <stdio.h>
int rename (const char *oldname, const char *newname)
Il modo usuale per spostare un file in C è usare rename(2), che a volte fallisce.
Se non puoi usare la chiamata di sistema rename(2) (ad es. perché sorgente e destinazione si trovano su filesystem diversi), devi interrogare la dimensione, i permessi e altri metadati del file sorgente con stat(2); copia i dati in loop su read(2), write(2) (usando un buffer di diversi kilobyte), open(2), close(2) e i metadati usando chmod(2), chown(2), utime(2) . Potresti anche preoccuparti di copiare gli attributi usando getxattr(2), setxattr(2), listxattr(2). In alcuni casi potresti anche usare sendfile(2), come commentato da David C. Rankin.
E se l'origine e la destinazione si trovano su filesystem diversi, non c'è modo di rendere la mossa atomica ed evitare condizioni di competizione (quindi usare rename(2) è preferibile quando possibile, perché è atomico secondo la sua pagina man). Il file sorgente può sempre essere modificato (da un altro processo) durante le operazioni di spostamento...
Quindi un modo pratico per spostare i file è provare prima a fare un rename(2), e se fallisce con EXDEV
(quando oldpath e nuovopercorso non si trovano sullo stesso filesystem montato), è necessario copiare byte e metadati. Diverse librerie forniscono funzioni che lo fanno, ad es. Qt QFile::rinomina.
Leggi Advanced Linux Programming - e vedi syscalls(2) - per saperne di più (e prova anche a strace
qualche mv
comando per capire cosa sta facendo). Quel libro è liberamente e legalmente scaricabile (quindi potresti trovarne diverse copie sul Web).
Il /bin/mv
command (vedi mv(1)) fa parte di GNU coreutils che è software libero. Potresti studiare il suo codice sorgente o usare strace(1) per capire cosa fa quel comando (in termini di syscalls(2)). In alcune shell Unix open source come sash o busybox, mv
potrebbe essere una shell incorporata. Vedi anche path_resolution(7) e glob(7).
Ci sono casi limite sottili (immagina un altro processo o pthread che esegue alcune operazioni sui file sullo stesso filesystem, directory o file). Leggi qualche manuale sui sistemi operativi per saperne di più.
Usare una combinazione di snprintf(3), system(3), mv(1) potrebbe essere complicato se il nome del file contiene caratteri strani come tab o
o newline, o inizia con un -
iniziale . Vedere errno(3).