Làm thế nào để bạn sử dụng các biểu thức thông thường với lệnh cp trong Linux?


22

Tôi đang cố gắng chỉ sao chép một tập hợp con các tập tin từ thư mục này sang thư mục khác bằng cách sử dụng cpthông báo cp: cannot stat [^\.php]': No such file or directory. Có cách nào để sử dụng các biểu thức thông thường chỉ bằng cách sử dụng cplệnh?

Câu trả lời:


29

Không.

Các cplệnh không có khả năng để xử lý bất kỳ của các đối số của nó như là biểu thức thông thường. Ngay cả các ký tự đại diện cũng không được xử lý bởi nó (hoặc hầu hết các tệp thực thi); thay vì chúng được xử lý bởi vỏ.

cp test/* test2/thực sự được mở rộng bằng bash và tất cả những gì cpthực sự nhìn thấy đối số của nó là cp test/file1 test/file2 test/file3 test2/(hoặc bất cứ điều gì phù hợp dựa trên nội dung thực tế của test/).

Ngoài ra, tôi không nghĩ biểu thức của bạn [^\.php], sẽ khớp với những gì bạn muốn (nó không khớp với các tệp có chứa .php).

Bạn có thể muốn xem xét findtiện ích để lọc ra danh sách các tệp dựa trên biểu thức chính quy, sau đó sử dụng xargsđể áp dụng danh sách tệp được trả về cho cplệnh (giả sử find không có trình xử lý tích hợp để sao chép tệp; Tôi ' m không quen thuộc với công cụ này).

Bạn có thể thử:

find . ! -iregex ".*\.php.*" -exec cp {} /destination/folder/ \;

Điều này nói rằng để tìm kiếm thư mục hiện tại một cách đệ quy cho các tệp không chứa ".php" trong đường dẫn và sao chép chúng vào /destination/folder/.

Theo yêu cầu, phân tích cụ thể hơn về các đối số:

  • . - Vị trí để bắt đầu tìm kiếm - trong trường hợp này, thư mục hiện tại
  • ! - Toán tử "Không", đảo ngược kết quả của lần kiểm tra tiếp theo
  • -iregex- Kiểm tra biểu thức chính quy không phân biệt chữ hoa chữ thường. Đối số tiếp theo là biểu thức.
  • ".*\.php.*"- Kết hợp biểu thức chính quy <Anything>.php<Anything>- Bất kỳ tệp nào có ".php" ở đâu đó trong đường dẫn. (Lưu ý, bao gồm cả trong thư mục chứa ".php" trong tên, bạn cần một biểu thức phức tạp hơn để chỉ khớp với các tệp)
  • -exec- Thực hiện một lệnh nếu các kiểm tra trước trả về đúng. Đối số tiếp theo là lệnh, tất cả các đối số còn lại sẽ ;được truyền cho lệnh. đó {}là một đối số đặc biệt đại diện cho tên tệp.
  • cp - Lệnh find` nên chạy trên mỗi tên đường dẫn phù hợp.
  • {}- Đường dẫn đến tệp được tìm thấy, được chuyển đến cpdưới dạng đối số để nó biết tệp nào cần sao chép
  • /destination/folder/- đối số được chuyển đến cp, cho biết cpnơi cần sao chép tệp vào.
  • \;- Đây là kẻ ;hủy diệt -execđang tìm kiếm. Chúng tôi thoát nó bằng cách \để shell của bạn không cố phân tích nó và thay vào đó, nó cung cấp nó như là một đối số cho lệnh ( find)

Đó là khá khó khăn để viết một biểu thức chính quy mà phù hợp với "chuỗi mà không có .php", vì vậy chúng tôi thay vì nói findđể tìm kiếm chuỗi làm chứa .phpvà sau đó nghịch kết quả với !.


2
find . -name [^\.php] -exec cp {} /path/to/location \;hãy cẩn thận cho các tập tin với các ký tự đặc biệt.
Cướp

@ Android Android - Cảm ơn. Tôi đã không biết rằng cpvà các nhị phân khác không thể mở rộng các biểu thức chính quy. Bạn có phiền khi giải thích ý nghĩa của từng tùy chọn và đối số trong ví dụ mẫu bạn đã đưa ra không? Tôi biết rằng .đề cập đến thư mục hiện hành nhưng những gì !, {}, \;, vv tham khảo cũng ý nghĩa của chúng? Ví dụ tại sao bạn phải thoát khỏi ;?
PeanutsMonkey

@Rob - Bạn có ý nghĩa gì với các tập tin đặc biệt?
PeanutsMonkey

@Rob - Tôi đã thử một biểu thức tương tự để xóa các tệp cụ thể tuy nhiên cuối cùng nó đã xóa tất cả các tệp trong thư mục. Lệnh của tôi là find . -name '[^\.txt]' -exec rm {} \;do đó tôi miễn cưỡng sử dụng find. Có lẽ là một lỗi về phía tôi nhưng không chắc chắn những gì tôi đã làm sai. Theo như sự hiểu biết của tôi {}đề cập đến từng tệp được tìm thấy bởi lệnhfind . -name '[^\.txt]'
PeanutsMonkey

Bạn đang cố gắng để phù hợp với regex là gì?
Cướp

10

Bạn có thể sử dụng một vài công cụ khác từ bảng điều khiển, như grep và xargs.

ls -1 some_folder | egrep 'some_extended_regex' | xargs cp -t destination_folder

Làm thế nào là {}khác nhau của -t?
PeanutsMonkey

2
Không có nhiều trong trường hợp này. Cú pháp thay thế cho xargs sẽ là 'xargs cp {} Destination_folder'. Cú pháp cp tiêu chuẩn lấy một hoặc nhiều nguồn và một đích cuối cùng, khi bạn sử dụng tùy chọn -t, bạn có thể chỉ định đích sau -t, sau đó sử dụng phần còn lại của dòng cho nguồn. Tôi chỉ tìm thấy tùy chọn -t thuận tiện hơn trong trường hợp này. Trong ví dụ khác, {} được thay thế bằng những gì được dẫn đến xargs (stdin), trong trường hợp này là tên tệp.
0xAF

-1

Bạn có thể chạy lệnh sau dễ sử dụng:

find /home/usr/search_dir -iname *file_name_portion*.txt | xargs cp -t /home/usr/destination_folder

tuyệt haa !!

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.