Giá trị gia tăng của tùy chọn -T trong GNU cp và mv là gì?


26

Tại sao một số lệnh GNU Coreutils có -T/--no-target-directorytùy chọn? Có vẻ như mọi thứ mà nó có thể đạt được bằng cách sử dụng ngữ nghĩa của .(dấu chấm tự) trong hệ thống phân cấp thư mục Unix truyền thống.

Xem xét:

cp -rT /this/source dir

Các -Ttùy chọn ngăn cản việc sao chép từ việc tạo ra một dir/sourcethư mục con. Thay vào đó /this/sourceđược xác định dirvà nội dung được ánh xạ giữa các cây tương ứng. Vì vậy, ví dụ /this/source/foo.cđi dir/foo.cvà hơn, hơn là để dir/source/foo.c.

Nhưng điều này có thể dễ dàng thực hiện mà không cần -Ttùy chọn sử dụng:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

Về mặt ngữ nghĩa, thành phần dấu chấm được sao chép như một đứa trẻ của dir, nhưng tất nhiên "đứa trẻ" đó đã tồn tại (vì vậy không phải tạo ra) và thực sự là dirchính nó, vì vậy hiệu quả /this/pathđược xác định dir.

Nó hoạt động tốt nếu thư mục hiện tại là mục tiêu:

cp -r /this/tree/node/. . # node's children go to current dir

Có điều gì bạn có thể làm chỉ với -Tđiều đó có thể hợp lý hóa sự tồn tại của nó? (Bên cạnh hỗ trợ cho các hệ điều hành không triển khai thư mục dấu chấm, một lý do không được đề cập trong tài liệu.)

Có phải mẹo chấm ở trên không giải quyết được các điều kiện chủng tộc giống như được đề cập trong tài liệu Thông tin GNU về -T?

Câu trả lời:


29

.Thủ thuật của bạn chỉ có thể được sử dụng khi bạn sao chép thư mục chứ không phải tệp. Các -Ttùy chọn làm việc với cả hai thư mục và tập tin. Nếu bạn làm:

cp srcfile destfile

và đã có một thư mục có tên destfilenó sẽ sao chép vào destfile/srcfile, có thể không có ý định. Vì vậy, bạn sử dụng

cp -T srcfile destfile

và bạn nhận được chính xác lỗi:

cp: cannot overwrite directory `destfile' with non-directory

Nếu bạn đã thử sử dụng .phương thức này, bản sao sẽ không bao giờ hoạt động:

cp: cannot stat `srcfile/.`: Not a directory

Thủ .thuật này hoạt động khi sao chép một tập tin, không phải khi đổi tên cơ sở của nó cùng một lúc! cp /path/to/file /target/dir/. Nếu /target/dir/filetồn tại và là một thư mục, bạn có được chẩn đoán tương tự! Nhưng bạn đã chỉ ra những gì -Tkhông thể thực hiện được nếu không có nó trong một bước, không có điều kiện chủng tộc: sao chép một tệp và thay đổi tên của nó mà không bị chuyển sang thư mục con.
Kaz

3
Điều đó không giống nhau - .mẹo bạn đang nói đến là nối /.vào nguồn .
Barmar

21

Vấn đề với cp/ mv/ lnnhư chúng được thiết kế ban đầu là chúng có hai lệnh trong một ( sao chépsao chép vào ).

cp A B

sao chép A sang B hoặc sao chép A vào B ( sao chép A sang B / A ) tùy thuộc vào việc có Btồn tại và là một thư mục hay không (và nhiều biến thể hơn nếu B là một liên kết tượng trưng đến một thư mục).

Điều đó thật tệ bởi vì nó mơ hồ. Vì vậy, việc triển khai GNU đã thêm các tùy chọn để giải quyết vấn đề đó.

cp -T A B

bản sao A đến B bất kể. Nếu Btồn tại và là một thư mục, điều đó sẽ thất bại (trừ khi bạn vượt qua -r). Trong mọi trường hợp, bạn sẽ không kết thúc với một Atệp bên trong Bkhi bạn dự định Ađược sao chép sang B.

Và:

cp -t B A

bản sao vào .


Triết lý unix ban đầu là cho rằng bạn biết những gì bạn làm, và sẽ vui vẻ cho phép bạn tự bắn vào chân mình.
Lenne

4
@Lenne, nhưng ở đây nó không cung cấp cho bạn một cách để tránh tự bắn vào chân mình. Nếu ai đó tạo thư mục B hoặc symlink đến thư mục nào đó ngay trước khi bạn chạy cp A B, lệnh sẽ không thực hiện những gì bạn dự định. Và làm [ -e B ] || [ -L B ] || cp A Bvẫn có một điều kiện chủng tộc cp -Tn A Bkhông có.
Stéphane Chazelas

6

-Tthể cung cấp một lỗi nếu một thư mục tồn tại không chính xác cho những gì nên là một tệp đích:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

Đó là, thay vì thành công khi bất ngờ sao chép thành một thư mục con, một trạng thái thoát cảnh báo và không tốt xảy ra, sau đó có thể khiến một tập lệnh hủy bỏ và con người kiểm tra xem tại sao có một thư mục không nên có trở thành một.


0

Sử dụng cờ cũng rõ ràng hơn nhiều và ít có nguy cơ xảy ra các hiệu ứng ngoài ý muốn, khi lệnh được sử dụng trong tập lệnh thay vì nhập thủ công. Vá các dấu chấm vào các đường dẫn trong một kịch bản có thể kết thúc bằng tất cả các loại nghịch ngợm bất ngờ.

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.