Chạy nhiều lệnh trong một dòng trong shell


388

Nói rằng tôi có một tập tin /templates/applevà tôi muốn

  1. đặt nó ở hai nơi khác nhau và sau đó
  2. xóa bản gốc.

Vì vậy, /templates/applesẽ được sao chép vào /templates/usedAND /templates/inuse và sau đó tôi muốn xóa bản gốc.

cpcách tốt nhất để làm điều này, theo sau rm? đây có phải là cách tốt hơn không?

Tôi muốn làm tất cả trong một dòng vì vậy tôi nghĩ nó sẽ trông giống như:

cp /templates/apple /templates/used | cp /templates/apple /templates/inuse | rm /templates/apple

Đây có phải là cú pháp đúng?

Câu trả lời:


792

Bạn đang sử dụng |(pipe) để hướng đầu ra của lệnh sang một lệnh khác. Những gì bạn đang tìm kiếm là &&toán tử để thực hiện lệnh tiếp theo chỉ khi lệnh trước thành công:

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple

Hoặc là

cp /templates/apple /templates/used && mv /templates/apple /templates/inuse

Để tóm tắt (không triệt để) các toán tử / dấu tách lệnh của bash:

  • |ống (đường ống) đầu ra tiêu chuẩn ( stdout) của một lệnh vào đầu vào tiêu chuẩn của một lệnh khác. Lưu ý rằng stderrvẫn đi vào đích mặc định của nó, bất cứ điều gì xảy ra.
  • |&dẫn cả hai stdoutstderrmột lệnh vào đầu vào tiêu chuẩn của một lệnh khác. Rất hữu ích, có sẵn trong bash phiên bản 4 trở lên.
  • &&thực hiện lệnh bên tay phải &&chỉ khi cái trước đó thành công.
  • ||thực hiện lệnh bên tay phải của ||nó, lệnh trước đó đã thất bại.
  • ;thực hiện lệnh bên phải ;luôn luôn bất kể lệnh trước đó thành công hay thất bại. Trừ khi set -eđược gọi trước đó, điều này gây ra bashlỗi.

6
Nâng cao. Tài liệu chính thức gnu.org/software/bash/manual/bash.html#Lists
Flow2k

78

Tại sao không cpđến vị trí 1, sau đó mvđến vị trí 2. Điều này quan tâm đến việc "xóa" bản gốc.

Và không, đó không phải là cú pháp chính xác. |được sử dụng để "ống" đầu ra từ một chương trình và biến nó thành đầu vào cho chương trình tiếp theo. Những gì bạn muốn là ;, mà tách biệt nhiều lệnh.

cp file1 file2 ; cp file1 file3 ; rm file1

Nếu bạn yêu cầu các lệnh riêng lẻ PHẢI thành công trước khi lệnh tiếp theo có thể được bắt đầu, thì bạn sẽ sử dụng &&thay thế:

cp file1 file2 && cp file1 file3 && rm file1

Theo cách đó, nếu một trong hai cplệnh không thành công, lệnh rmsẽ không chạy.


10

Lưu ý đó cp A B; rm Alà chính xác mv A B. Nó cũng sẽ nhanh hơn, vì bạn không thực sự phải sao chép các byte (giả sử đích đến nằm trên cùng một hệ thống tệp), chỉ cần đổi tên tệp. Vậy bạn muốncp A B; mv A C


7

Một tùy chọn khác là gõ Ctrl+V Ctrl+Jvào cuối mỗi lệnh.

Ví dụ (thay thế #bằng Ctrl+V Ctrl+J):

$ echo 1#
echo 2#
echo 3

Đầu ra:

1
2
3

Điều này sẽ thực thi các lệnh bất kể nếu những lần trước thất bại.

Giống như: echo 1; echo 2; echo 3

Nếu bạn muốn dừng thực thi trên các lệnh thất bại, hãy thêm &&vào cuối mỗi dòng trừ dòng cuối cùng.

Ví dụ (thay thế #bằng Ctrl+V Ctrl+J):

$ echo 1 &&#
failed-command &&#
echo 2

Đầu ra:

1
failed-command: command not found

Trong zshbạn cũng có thể sử dụng Alt+Enterhoặc Esc+Enterthay vìCtrl+V Ctrl+J


3

Thử cái này..

cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apple


2

Sử dụng đường ống có vẻ kỳ lạ với tôi. Dù sao, bạn nên sử dụng andtoán tử Bash logic :

$ cp /templates/apple /templates/used && cp /templates/apple /templates/inuse && rm /templates/apples

Nếu các cplệnh thất bại, rmsẽ không được thực thi.

Hoặc, bạn có thể tạo một dòng lệnh phức tạp hơn bằng cách sử dụng một forvòng lặp và cmp.

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.