- Plattform: Debian Wheezy 3.2.0-4-686-pae
- Compiler: GCC (Debian 4.7.2-5) 4.7.2 (Code::Blocks)
Ich möchte eine Datei von einem Speicherort an einen anderen verschieben. Nichts ist so kompliziert wie das Verschieben auf verschiedene Laufwerke oder in verschiedene Dateisysteme. Ich weiß, dass die “Standardmethode” darin besteht, einfach die Datei zu kopieren und dann das Original zu entfernen. Aber ich möchte eine Möglichkeit, den Besitz der Datei, den Modus, den letzten Zugriff/die letzte Änderung usw. beizubehalten. Ich gehe davon aus, dass ich die Datei kopieren und anschließend den Besitz, den Modus usw. der neuen Datei bearbeiten muss, aber ich habe keine Ahnung, wie das geht.
Die übliche Methode zum Verschieben einer Datei in C ist die Verwendung von umbenennen(2)die manchmal scheitern.
Wenn Sie die nicht verwenden können umbenennen(2) syscall (z. B. weil Quelle und Ziel auf unterschiedlichen Dateisystemen liegen), müssen Sie die Größe, Berechtigung und andere Metadaten der Quelldatei mit abfragen Statistik(2); Kopieren Sie die Datenschleife auf lesen (2), schreiben(2) (unter Verwendung eines Puffers von mehreren Kilobyte), offen(2), schließen(2) und die Metadaten verwenden chmod(2), chown(2), Laufzeit(2). Möglicherweise interessieren Sie sich auch für das Kopieren von Attributen mit getxattr(2), setxattr(2), listxattr(2). Sie könnten auch in einigen Fällen verwenden sendfile(2)wie von David C. Rankin kommentiert.
Und wenn sich Quelle und Ziel auf unterschiedlichen Dateisystemen befinden, gibt es keine Möglichkeit, die Bewegung atomar zu machen und Race-Conditions zu vermeiden (Also using umbenennen(2) ist nach Möglichkeit vorzuziehen, da es laut seiner Manpage atomar ist). Die Quelldatei kann während der Verschiebevorgänge immer (durch einen anderen Prozess) geändert werden …
Eine praktische Methode zum Verschieben von Dateien besteht also darin, zunächst Folgendes zu tun: umbenennen(2)und wenn das mit fehlschlägt EXDEV
(wann alter Pfad und neuer Weg sich nicht auf demselben gemounteten Dateisystem befinden), müssen Sie Bytes und Metadaten kopieren. Mehrere Bibliotheken bieten dafür Funktionen an, zB Qt QDatei::umbenennen.
Lesen Fortgeschrittene Linux-Programmierung – und sehen Systemaufrufe(2) – für mehr (und versuchen Sie es auch strace
manche mv
Befehl, um zu verstehen, was es tut). Dieses Buch kann kostenlos und legal heruntergeladen werden (so dass Sie mehrere Exemplare im Internet finden können).
Das /bin/mv
Befehl (vgl mv(1)) ist ein Teil von GNU Coreutils welches ist gratis Software. Sie könnten entweder den Quellcode studieren oder verwenden spur(1) um zu verstehen, was dieser Befehl tut (in Bezug auf Systemaufrufe(2)). In einigen Open Source Unix-Shells mögen Schärpe oder Busybox, mv
könnte eine eingebaute Shell sein. Siehe auch Pfadauflösung(7) und Kugel(7).
Es gibt subtile Eckfälle (stellen Sie sich einen anderen Prozess oder Pthread vor, der einige Dateioperationen auf demselben Dateisystem, Verzeichnis oder denselben Dateien ausführt). Lesen Sie einige Betriebssystem Lehrbuch für mehr.
Mit einer Mischung aus snprintf(3), System(3), mv(1) könnte schwierig sein, wenn der Dateiname seltsame Zeichen enthält, wie z Tab oder
oder Zeilenumbrüche oder beginnt mit einem Anfangsbuchstaben -
. Sehen Fehlernummer(3).
Wenn sich der ursprüngliche und der neue Speicherort für die Datei auf demselben Dateisystem befinden, ist ein “Verschieben” konzeptionell identisch mit einem “umbenennen.”
#include <stdio.h>
int rename (const char *oldname, const char *newname)