Miễn là bạn không di chuyển tệp qua biên giới hệ thống tệp, thao tác sẽ an toàn. Điều này là do cơ chế, làm thế nào »di chuyển« thực sự được thực hiện.
Nếu bạn mv
là một tệp trên cùng một hệ thống tệp, thì tệp đó không thực sự được chạm vào mà chỉ thay đổi mục nhập hệ thống tệp.
$ mv foo bar
thực sự làm một cái gì đó như
$ ln foo bar
$ rm foo
Điều này sẽ tạo ra một liên kết cứng (mục nhập thư mục thứ hai) cho tệp (thực tế là nút được trỏ bởi mục nhập hệ thống tệp) foo
được đặt tên bar
và xóa foo
mục nhập. Kể từ bây giờ khi gỡ bỏ foo
, có một mục nhập hệ thống tệp thứ hai trỏ đến foo
nút inode, loại bỏ mục nhập cũ foo
không thực sự loại bỏ bất kỳ khối nào thuộc về inode.
Chương trình của bạn sẽ vui vẻ nối thêm vào tập tin, vì xử lý tệp đang mở của nó trỏ đến nút của tệp chứ không phải mục nhập hệ thống tệp.
Lưu ý: Nếu chương trình của bạn đóng và mở lại tệp giữa các lần ghi, cuối cùng bạn sẽ có một tệp mới được tạo bằng mục nhập hệ thống tệp cũ!
Di chuyển hệ thống tập tin chéo:
Nếu bạn di chuyển tệp qua biên giới hệ thống tệp, mọi thứ sẽ trở nên tồi tệ. Trong trường hợp này, bạn không thể đảm bảo giữ cho tệp của mình được nhất quán, vì mv
thực tế sẽ
- tạo một tệp mới trên hệ thống tệp đích
- sao chép nội dung của tập tin cũ sang tập tin mới
- xóa tập tin cũ
hoặc là
$ cp /path/to/foo /path/to/bar
$ rm /path/to/foo
tôn trọng.
$ touch /path/to/bar
$ cat < /path/to/foo > /path/to/bar
$ rm /path/to/foo
Tùy thuộc vào việc sao chép có đạt đến cuối tệp trong quá trình ghi ứng dụng của bạn hay không, có thể xảy ra rằng bạn chỉ có một nửa dòng trong tệp mới.
Ngoài ra, nếu ứng dụng của bạn không đóng và mở lại tệp cũ, nó sẽ tiếp tục ghi vào tệp cũ, ngay cả khi nó dường như bị xóa: kernel biết tệp nào đang mở và mặc dù nó sẽ xóa mục nhập hệ thống tệp, nó sẽ không xóa inode của các tập tin cũ và các khối liên quan cho đến khi ứng dụng của bạn đóng xử lý tệp đang mở.
rename()
cuộc gọi hệ thống. Vì vậy, phiên bản gốcmv
thực sự đã gọilink()
để tạo liên kết cứng, tiếp theo làunlink()
xóa tên gốc.rename()
đã được thêm vào FreeBSD, để thực hiện điều này một cách nguyên tử trong kernel.