Tại sao mv không thể đối phó với sự tồn tại của thư mục cùng tên ở đích?


8

mv không thể di chuyển một thư mục đến đích bằng một thư mục cùng tên:

$ mv fortran/ imperative_PLs/
mv: cannot move ‘fortran/’ to ‘imperative_PLs/fortran’: Directory not empty
  1. Tại sao mvkhông hoạt động trong trường hợp này? Điều đó có thể được giải thích từ các cuộc gọi hệ thống mv? (So ​​sánh với rsynccái nào có thể)

  2. Tại sao được mvthiết kế để không hoạt động trong trường hợp này? Lý do hoặc điểm là gì?

Câu trả lời:


6
  1. mvkhông hoạt động trong trường hợp này vì nó không được thiết kế để làm như vậy. Các cuộc gọi hệ thống là (có thể) hoặc

    • Di chuyển đến cùng hệ thống tập tin: rename(ban đầu linkunlink)
    • Di chuyển qua các hệ thống tệp: sao chép tệp đệ quy theo sau là đệ quy unlink
  2. Ý kiến: Tôi nghĩ rằng nó không quá nhiều đến nỗi nó được thiết kế để không hoạt động, vì nó không được thiết kế để xử lý trường hợp sử dụng này. Đối với một công cụ "đơn giản" có ý định làm tốt một việc bạn cần cung cấp một bộ công tắc để chỉ ra mvđường dẫn hành động nào sẽ thực hiện:

    • Bảo lãnh với một lỗi, như trong việc thực hiện hiện tại
    • Để hợp nhất, bảo lãnh với một lỗi nếu một tệp đã tồn tại
    • Để hợp nhất, thay thế bất kỳ tệp mục tiêu nào đã tồn tại

Nếu việc hợp nhất / thay thế hành động là những gì bạn muốn, bạn có thể thực hiện nó một cách dễ dàng đủ với cptiếp theo rm, hoặc bằng cách sử dụng một trong những cây tập tin sao chép tiện ích tar, paxvv


Cảm ơn. (1) Có rmgọi rmdir()bên cạnh rename()không? (2) "Di chuyển đến cùng một hệ thống tập tin: đổi tên (liên kết ban đầu và hủy liên kết)", ý của bạn là "liên kết ban đầu và hủy liên kết" là gì? (3) Khi Di chuyển qua các hệ thống tệp, tại sao "sao chép tệp đệ quy theo sau là hủy liên kết đệ quy"?
Tim

lỗi đánh máy của tôi Ý tôi là mvthay vì rm.
Tim

@Tim: Trong cùng một hệ thống tập tin, chỉmv sử dụng . Giữa các hệ thống tệp, về cơ bản giống như (nhưng hãy cẩn thận khi xử lý các tệp đặc biệt như symlink, thiết bị, v.v., theo truyền thống, không được xử lý tốt ) theo sau , vì vậy, nó sử dụng trong chế độ đó. rename()mvcp -rcp -rrm -rrmdir()
Guntram Blohm hỗ trợ Monica

10

mvrsynckhông phải là chương trình tương tự. Cụ thể, mvthường cố gắng đổi tên các đối tượng. Nếu nó trong cùng một hệ thống tập tin, nó hoàn toàn không sao chép nội dung.

Nếu bạn chưa có imperative_PLs/fortran, thì mvsẽ lấy fortranthư mục hiện có và đổi tên nó thành điểm đó trong cây.

Nhưng bạn đã có một thư mục (có nội dung) tại vị trí đó. Vì một tên chỉ có thể tham chiếu một đối tượng duy nhất, thư mục hiện có sẽ phải bị xóa hoặc đổi tên. mvgiả sử bạn không muốn làm một trong hai và hủy bỏ.

rsyncthay vào đó sao chép các tệp riêng lẻ và các nội dung khác bên trong fortranvà đặt chúng vào imperative_PLs/fortranthư mục hiện có .

renameThay vào đó, hãy nghĩ về nó và hành vi có vẻ dễ hiểu hơn.


7

mvlà thực sự renamedưới vỏ bọc.

Nếu bạn di chuyển một tệp sang một tệp khác, mvgiả sử bạn biết bạn đang làm gì và ghi đè lên tệp đích.

Nếu bạn di chuyển một thư mục sang thư mục khác, mvgiả sử bạn muốn giữ tên cơ sở của thư mục gốc và tạo nó trên thư mục đích. Nếu chưa có một thư mục có tên đó ở phía đích hoặc nếu một thư mục có tên đó tồn tại nhưng trống thì thao tác thành công.

Tuy nhiên, nếu thư mục đích đã tồn tại và không trống, thì đây không còn renamelà một tệp đệ quy và loại bỏ thư mục. renamekhông được thiết kế để làm điều đó nên nó thất bại, mvkhông đi xa hơn vì nó cho rằng bạn không muốn làm điều đó và cũng thất bại.


Cảm ơn. Có rmgọi rmdir()bên cạnh rename()không?
Tim

1
@Tim: rmkhông bao giờ gọi rename(). Nhưng nó gọi rmdir()khi được cung cấp -rtùy chọn.
Guntram Blohm hỗ trợ Monica

@Gun: Lỗi đánh máy của tôi. Ý tôi là mvthay vì rm.
Tim

1
mvrmdir()chỉ gọi nếu hệ thống tệp nguồn và đích là khác nhau. Một lý do là nó không còn giống như vậy mà có một đường dẫn mới.
jlliagre

3

Thông báo lỗi khi di chuyển giữa các hệ thống tập tin dài hơn một chút:

# mv a/foo b/bar
mv: inter-device move failed: 'a/foo' to 'b/bar/foo'; unable to remove target: Directory not empty

Vì vậy, nó không cố gắng hợp nhất các thư mục như bạn mong đợi, thay vào đó, nó sẽ xóa mục tiêu trước khi đổi tên nguồn; và loại bỏ cho các thư mục chỉ hoạt động khi nó trống.

Về mặt tòa nhà, trong cùng một hệ thống tập tin, nó chỉ là rename()

rename("a/foo", "a/bar/foo")            = -1 ENOTEMPTY (Directory not empty)

Khi di chuyển giữa các hệ thống tập tin, lần đầu tiên rename()phát hiện trường hợp này và chúng cố gắng đơn giản rmdir().

rename("a/foo", "b/bar/foo")            = -1 EXDEV (Invalid cross-device link)
rmdir("b/bar/foo")                      = -1 ENOTEMPTY (Directory not empty)

mvcó thể nỗ lực nhiều hơn nhưng nó không muốn. ;)


cảm ơn. có mvgọi rmdir()không Tôi cố gắng một với strace -e trace=filetrên mv, rmdir()không đi lên.
Tim

chỉ khi vượt qua ranh giới hệ thống tập tin, nếu không tôi đoán nó rename()xử lý nội bộ
frostschutz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.