Tak długo, jak nie przenosisz pliku poza granice systemu plików, operacja powinna być bezpieczna. Wynika to z mechanizmu, w jaki sposób „przenoszenie” jest faktycznie wykonywane.
Jeśli mv
plik znajduje się w tym samym systemie plików, plik nie jest tak naprawdę dotykany, ale zmieniany jest tylko wpis w systemie plików.
$ mv foo bar
faktycznie robi coś takiego
$ ln foo bar
$ rm foo
Spowoduje to utworzenie twardego łącza (drugiego wpisu katalogu) dla pliku (w rzeczywistości i-węzła wskazywanego przez wpis w systemie plików) o foo
nazwie bar
i usunięcie foo
wpisu. Ponieważ teraz podczas usuwania foo
jest drugi wpis systemu plików wskazujący na foo
i-węzeł, usunięcie starego wpisu foo
tak naprawdę nie usuwa żadnych bloków należących do i-węzła.
Twój program i tak chętnie dołączy do pliku, ponieważ jego otwarty uchwyt pliku wskazuje na i-węzeł pliku, a nie pozycję systemu plików.
Uwaga: Jeśli twój program zamyka się i ponownie otwiera plik między zapisami, skończyłoby się to utworzeniem nowego pliku przy użyciu starego wpisu systemu plików!
Przenoszenie między systemami plików:
Jeśli przeniesiesz plik poza granice systemu plików, sytuacja stanie się brzydka. W takim przypadku nie można zagwarantować, że plik będzie spójny, ponieważ mv
tak naprawdę byłoby
- utwórz nowy plik w docelowym systemie plików
- skopiuj zawartość starego pliku do nowego pliku
- usuń stary plik
lub
$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo
odpowiednio
$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo
W zależności od tego, czy kopiowanie osiąga koniec pliku podczas zapisu aplikacji, może się zdarzyć, że w nowym pliku jest tylko połowa wiersza.
Dodatkowo, jeśli twoja aplikacja nie zamknie się i nie otworzy ponownie starego pliku, kontynuuje zapisywanie do starego pliku, nawet jeśli wydaje się, że został usunięty: jądro wie, które pliki są otwarte i chociaż usunie pozycję systemu plików, nie usunie i-węzła starego pliku i powiązanych bloków, dopóki aplikacja nie zamknie otwartego uchwytu pliku.
rename()
wywołania systemowego. Oryginalna wersjamv
faktycznie wywołała połączenielink()
twarde, a następnieunlink()
usunęła pierwotną nazwę.rename()
został dodany w FreeBSD, aby zaimplementować to atomowo w jądrze.