Làm thế nào để sao chép một số, nhưng không phải tất cả các tập tin?


54

Vì vậy, bạn có thể sử dụng *làm thẻ đại diện cho tất cả các tệp khi sử dụng cptrong ngữ cảnh của một thư mục. Có cách nào để sao chép tất cả các tập tin ngoại trừ xtập tin?

Câu trả lời:


42

Trong bashbạn có thể sử dụng extglob:

 $ shopt -s extglob  # to enable extglob
 $ cp !(b*) new_dir/

nơi !(b*)loại trừ tất cả b*các tập tin.

Sau này bạn có thể vô hiệu hóa extglobvới

 $ shopt -u extglob

Bạn có biết nếu có cái gì đó tương đương với vỏ tcsh?
Levon

Thật không may, tôi không. Có vẻ như findlà cách duy nhất trong tcsh:find . -maxdepth 1 ! -name "exclude*" -exec cp -t destination {} \+
vội vàng

50

Rupync xử lý việc này độc đáo.

Ví dụ sao chép tất cả: rsync -aP /folder1/* /folder/2

Ví dụ sao chép tất cả với loại trừ: rsync -aP --exclude=x /folder1/* /folder2/

Công -aPtắc:

a: Tương tự cp -a, đệ quy, v.v ... P: Hiển thị tiến trình, một tính năng hay của rsync.


5
Và xem câu trả lời này để biết hướng dẫn ngắn về danh sách loại trừ rsync phổ biến.
Gilles 'SO- ngừng trở nên xấu xa'

1
Trên darwin / MacOS, sử dụng -rPthay vì -aPnếu bạn muốn lặp lại. -alà để lưu trữ. Không chắc chắn nếu điều này thay đổi hoặc nếu nó chỉ khác trên MacOS.
jpoveda

rsynckhông có tùy chọn để làm cho nó đệ quy. Ví dụ : rsync --recursive -P --exclude=x /folder1/* /folder2/. (Chỉ được thử nghiệm trên Ubuntu)
n1k31t4

12

Đây không phải là một tính năng của cp, nó là một tính năng của trình bao của bạn (nó mở rộng *nghĩa là tất cả các tệp không có dấu chấm), vì vậy câu trả lời phụ thuộc vào việc bạn đang sử dụng trình bao nào. Ví dụ: zshhỗ trợ cú pháp này:

$ cp ^x /path/to/destination

Trong đó ^xcó nghĩa là "tất cả các tệp ngoại trừ x"

Bạn cũng có thể kết hợp các mẫu lựa chọn và loại bỏ lựa chọn, ví dụ để sao chép tất cả các tệp wav ngoại trừ các tệp có chứa xyz, bạn có thể sử dụng:

cp *.wav~*xyz*

Có ý kiến bashgì về ?
Chad Harrison

@hydroparadise Tôi không biết nhiều về bash, nhưng câu trả lời này dường như bao trùm nó
Michael Mrozek

Thế còn tcsh? Có ai biết không?
Levon

4

Cũng có thể được thực hiện trong vỏ bourne cũ (di động / tương thích) đơn giản bằng nhiều cách khác nhau với các công cụ tiêu chuẩn theo nhiều cách kém thanh lịch hơn so với sử dụng các lệnh toàn cầu hoặc trình bao vỏ tiên tiến với các tùy chọn loại trừ tích hợp.

Nếu không có quá nhiều tệp (và không có tên bao gồm khoảng trắng và / hoặc ngắt dòng), đây có thể là một cách:

cp `ls | egrep -v '^excludename$'` destdir/.

Chắc chắn, bashvà các công cụ GNU rất tuyệt vời và mạnh mẽ, nhưng chúng vẫn không phải lúc nào cũng có sẵn. Nếu bạn có ý định đưa nó vào một kịch bản di động, tôi sẽ đề xuất findnhư trong nhận xét của Rush.


2
Tôi thấy rằng phần cuối của câu trả lời của bạn chỉ làm mất tập trung từ chủ đề trong tay. Bên cạnh đó, "Unix" không còn là tiêu chuẩn vàng nữa (nếu có). Nó không liên quan nếu có thứ gì đó là "Unix" hay không nữa, mặc dù tiêu đề của trang này là "Unix và Linux".
Alexander

2
ĐỒNG Ý. Tôi đã chuyển bình luận đến đây thay vào đó: Unix không phải là GNU. Tôi đồng ý rằng "sự không trộn lẫn" của mọi thứ không thú vị lắm, nhưng tôi vẫn tin vào tính di động và biết một chút về lịch sử của bạn.
MattBianco

Hoàn toàn đồng ý với bạn ở đó.
Alexander

2

Nếu bạn muốn sao chép mọi thứ trong một thư mục (bao gồm cả các thư mục con) vào một thư mục con cụ thể:

cp -R $(ls | grep -v '^subdir$') subdir/

Hoạt động với sh, bash, zsh (ít nhất).


1
Hãy thuyết phục tôi điều này không giống với ý địnhcp -R * subdir/
roaima

1
Nếu bạn sử dụng lệnh "cp -R * subir /", bash / zsh đã cố gắng sao chép 'subir' một cách chính xác. Bạn kết thúc với một lỗi: "tên quá dài (không được sao chép)".
user2707671

Điểm tốt. Đề xuất của bạn cố gắng tránh cảnh báo từ cp(không phải từ bash/ sh), " cp: cannot copy a directory, ‘subdir’, into itself, ‘subdir/subdir’". Bản sao hoàn thành chính xác, mặc dù. Thật không may, biến thể của bạn bị hỏng với bất kỳ tên tệp nào chứa dấu chấm câu có dấu cách hoặc dấu cách. Xem unix.stackexchange.com/q/128985/135943
roaima

-1

extglob là cách tốt nhất cho đến nay tôi đoán.

Một cách khác là sử dụng cp $(ls --ignore=x) subdir/


Điều này sẽ phá vỡ bất kỳ hình thức nhân vật đặc biệt nào trong tên tập tin. (Dấu cách, dòng mới, $v.v.) Không bao giờ phân tích đầu ra của ls. unix.stackexchange.com/q/128985/135943
tự đại diện
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.