Các toán tử điều khiển và chuyển hướng của shell là gì?


245

Tôi thường thấy các hướng dẫn trực tuyến kết nối các lệnh khác nhau với các biểu tượng khác nhau. Ví dụ:

command1 |  command2
command1 &  command2
command1 || command2    
command1 && command2

Những người khác dường như đang kết nối các lệnh với các tệp:

command1  > file1
command1  >> file1

Những thứ này là gì? Họ được gọi là gì? Họ làm gì? Có nhiều trong số họ?


Chủ đề meta về câu hỏi này. .

Câu trả lời:


340

Chúng được gọi là toán tử shell và vâng, có nhiều hơn trong số chúng. Tôi sẽ đưa ra một cái nhìn tổng quan ngắn gọn về phổ biến nhất trong số hai lớp chính, toán tử điều khiểntoán tử chuyển hướng và cách chúng hoạt động đối với bash shell.

A. Toán tử điều khiển

Trong ngôn ngữ lệnh shell, mã thông báo thực hiện chức năng điều khiển.
Đây là một trong những biểu tượng sau:

&   &&   (   )   ;   ;;   <newline>   |   ||

|&trong bash.

Một !không một nhà điều hành kiểm soát nhưng một Lời Reserved . Nó trở thành logic KHÔNG [toán tử phủ định] bên trong Biểu thức số học và bên trong các cấu trúc kiểm tra (trong khi vẫn yêu cầu một dấu phân cách không gian).

A.1 Danh sách đầu mối

  • ; : Sẽ chạy một lệnh sau khi lệnh khác kết thúc, bất kể kết quả của lệnh đầu tiên.

    command1 ; command2

    Đầu tiên command1là chạy, ở phía trước và sau khi hoàn thành, command2nó sẽ được chạy.

    Một dòng mới không có trong một chuỗi bằng chữ hoặc sau một số từ khóa nhất định không tương đương với toán tử dấu chấm phẩy. Danh sách các ;lệnh đơn giản được phân tách vẫn là một danh sách - vì trình phân tích cú pháp của shell vẫn phải tiếp tục đọc trong các lệnh đơn giản tuân theo ;lệnh đơn giản được phân tách trước khi thực hiện, trong khi một dòng mới có thể phân định toàn bộ danh sách lệnh - hoặc danh sách danh sách. Sự khác biệt là tinh tế, nhưng phức tạp: do shell không có sự bắt buộc trước đó để đọc dữ liệu theo dòng mới, dòng mới đánh dấu một điểm mà shell có thể bắt đầu đánh giá các lệnh đơn giản mà nó đã đọc, trong khi đó ;dấu chấm phẩy không phải.

  • & : Điều này sẽ chạy một lệnh trong nền, cho phép bạn tiếp tục làm việc trong cùng một shell.

     command1 & command2

    Tại đây, command1được khởi chạy ở chế độ nền và command2bắt đầu chạy ở nền trước ngay lập tức mà không cần chờ command1thoát.

    Một dòng mới sau command1là tùy chọn.

A.2 Toán tử logic

  • && : Được sử dụng để xây dựng danh sách AND, nó cho phép bạn chạy một lệnh chỉ khi một lệnh khác thoát thành công.

     command1 && command2

    Ở đây, command2sẽ chạy sau khi command1kết thúc và chỉ khi command1thành công (nếu mã thoát của nó là 0). Cả hai lệnh được chạy ở nền trước.

    Lệnh này cũng có thể được viết

    if command1
    then command2
    else false
    fi

    hoặc đơn giản là if command1; then command2; finếu trạng thái trả lại bị bỏ qua.

  • || : Được sử dụng để xây dựng danh sách OR, nó cho phép bạn chạy một lệnh chỉ khi một lệnh khác không thành công.

     command1 || command2

    Ở đây, command2sẽ chỉ chạy nếu command1thất bại (nếu nó trả về trạng thái thoát khác 0). Cả hai lệnh được chạy ở nền trước.

    Lệnh này cũng có thể được viết

    if command1
    then true
    else command2
    fi

    hoặc theo cách ngắn hơn if ! command1; then command2; fi.

    Lưu ý rằng &&||được liên kết trái; xem Ưu tiên của toán tử logic shell &&, || để biết thêm thông tin.

  • !: Đây là một từ dành riêng đóng vai trò là toán tử không phải của người dùng (nhưng phải có dấu phân cách), được sử dụng để phủ định trạng thái trả về của lệnh - return 0 nếu lệnh trả về trạng thái khác 0, trả về 1 nếu nó trả về trạng thái 0 . Cũng là một logic KHÔNG cho các testtiện ích.

    ! command1
    
    [ ! a = a ]

    Và một toán tử KHÔNG thực sự bên trong Biểu thức số học:

    $ echo $((!0)) $((!23))
    1 0

A.3 Vận hành ống

  • |: Toán tử đường ống, nó chuyển đầu ra của một lệnh làm đầu vào cho lệnh khác. Một lệnh được xây dựng từ toán tử đường ống được gọi là đường ống .

     command1 | command2

    Bất kỳ đầu ra được in bởi command1được chuyển qua như là đầu vào command2.

  • |&: Đây là một tốc ký cho 2>&1 |bash và zsh. Nó chuyển cả đầu ra tiêu chuẩn và lỗi tiêu chuẩn của một lệnh làm đầu vào cho một lệnh khác.

    command1 |& command2

A.4 Danh sách chấm câu khác

;;chỉ được sử dụng để đánh dấu sự kết thúc của một tuyên bố trường hợp . Ksh, bash và zsh cũng hỗ trợ ;&chuyển sang trường hợp tiếp theo và ;;&(không phải trong ATT ksh) để tiếp tục và kiểm tra các trường hợp tiếp theo.

()được sử dụng để nhóm các lệnh và khởi chạy chúng trong một lớp con. {}cũng nhóm các lệnh, nhưng không khởi chạy chúng trong một lớp con. Xem câu trả lời này để thảo luận về các loại dấu ngoặc đơn, dấu ngoặc và dấu ngoặc trong cú pháp shell.

B. Toán tử chuyển hướng

Toán tử chuyển hướng

Trong ngôn ngữ lệnh shell, mã thông báo thực hiện chức năng chuyển hướng. Đây là một trong những biểu tượng sau:

<     >     >|     <<     >>     <&     >&     <<-     <>

Điều này cho phép bạn kiểm soát đầu vào và đầu ra của các lệnh của bạn. Chúng có thể xuất hiện ở bất cứ đâu trong một lệnh đơn giản hoặc có thể theo lệnh. Chuyển hướng được xử lý theo thứ tự chúng xuất hiện, từ trái sang phải.

  • < : Cung cấp đầu vào cho một lệnh.

    command < file.txt

    Ở trên sẽ thực hiện commandtrên các nội dung của file.txt.

  • <>: giống như trên, nhưng tệp được mở ở chế độ đọc + ghi thay vì chỉ đọc :

    command <> file.txt

    Nếu tập tin không tồn tại, nó sẽ được tạo.

    Toán tử đó hiếm khi được sử dụng vì các lệnh thường chỉ đọc từ stdin của chúng, mặc dù nó có thể có ích trong một số tình huống cụ thể .

  • > : Hướng đầu ra của lệnh vào một tệp.

    command > out.txt

    Ở trên sẽ tiết kiệm đầu ra commandnhư out.txt. Nếu tệp tồn tại, nội dung của nó sẽ bị ghi đè và nếu không tồn tại, nó sẽ được tạo.

    Toán tử này cũng thường được sử dụng để chọn xem có nên in thứ gì đó thành lỗi tiêu chuẩn hoặc đầu ra tiêu chuẩn hay không :

    command >out.txt 2>error.txt

    Trong ví dụ trên, >sẽ chuyển hướng đầu ra tiêu chuẩn và 2>chuyển hướng lỗi tiêu chuẩn. Đầu ra cũng có thể được chuyển hướng bằng cách sử dụng 1>, nhưng vì đây là mặc định, nên 1thường được bỏ qua và nó được viết đơn giản là >.

    Vì vậy, để chạy commandtrên file.txtvà lưu lượng của nó trong out.txtvà bất kỳ thông báo lỗi trong error.txtbạn sẽ chạy:

    command < file.txt > out.txt 2> error.txt
  • >|: Không giống như >, nhưng sẽ ghi đè lên mục tiêu, ngay cả khi trình bao đã được cấu hình để từ chối ghi đè (có set -Choặc set -o noclobber).

    command >| out.txt

    Nếu out.txttồn tại, đầu ra của commandsẽ thay thế nội dung của nó. Nếu nó không tồn tại, nó sẽ được tạo ra.

  • >>: Không giống như >, ngoại trừ nếu tệp mục tiêu tồn tại, dữ liệu mới sẽ được nối thêm.

    command >> out.txt

    Nếu out.txttồn tại, đầu ra của commandnó sẽ được thêm vào nó, sau bất cứ thứ gì đã có trong đó. Nếu nó không tồn tại, nó sẽ được tạo ra.

  • &>, >&, >>&&>>: (không chuẩn). Chuyển hướng cả lỗi tiêu chuẩn và đầu ra tiêu chuẩn, thay thế hoặc nối thêm, tương ứng.

    command &> out.txt

    Cả lỗi tiêu chuẩn và đầu ra tiêu chuẩn của commandsẽ được lưu vào out.txt, ghi đè lên nội dung của nó hoặc tạo ra nó nếu nó không tồn tại.

    command &>> out.txt

    Như trên, ngoại trừ nếu out.txttồn tại, đầu ra và lỗi của commandsẽ được thêm vào nó.

    Các &>biến thể bắt nguồn từ bash, trong khi các >&biến thể đến từ csh (thập kỷ trước). Cả hai đều xung đột với các toán tử shell POSIX khác và không nên được sử dụng trong các shtập lệnh di động .

  • <<: Một tài liệu ở đây. Nó thường được sử dụng để in các chuỗi nhiều dòng.

     command << WORD
         Text
     WORD

    Ở đây, commandsẽ lấy mọi thứ cho đến khi nó tìm thấy sự xuất hiện tiếp theo của WORD, Texttrong ví dụ trên, làm đầu vào. Mặc dù WORDthường EoFhoặc biến thể của nó, nó có thể là bất kỳ chuỗi ký tự chữ và số (và không chỉ) mà bạn thích. Khi WORDđược trích dẫn, văn bản trong tài liệu ở đây được xử lý theo nghĩa đen và không có phần mở rộng nào được thực hiện (ví dụ về các biến). Nếu nó không được trích dẫn, các biến sẽ được mở rộng. Để biết thêm chi tiết, xem hướng dẫn bash .

    Nếu bạn muốn đặt đầu ra command << WORD ... WORDtrực tiếp vào một lệnh hoặc lệnh khác, bạn phải đặt ống trên cùng một dòng với << WORD, bạn không thể đặt nó sau khi kết thúc WORD hoặc trên dòng sau. Ví dụ:

     command << WORD | command2 | command3...
         Text
     WORD
  • <<<: Ở đây các chuỗi, tương tự như các tài liệu ở đây, nhưng dành cho một dòng duy nhất. Chúng chỉ tồn tại trong cổng Unix hoặc RC (nơi nó bắt nguồn), zsh, một số triển khai của ksh, yash và bash.

    command <<< WORD

    Bất cứ điều gì được đưa ra khi WORDđược mở rộng và giá trị của nó được chuyển qua làm đầu vào command. Điều này thường được sử dụng để truyền nội dung của các biến làm đầu vào cho một lệnh. Ví dụ:

     $ foo="bar"
     $ sed 's/a/A/' <<< "$foo"
     bAr
     # as a short-cut for the standard:
     $ printf '%s\n' "$foo" | sed 's/a/A/'
     bAr
     # or
     sed 's/a/A/' << EOF
     $foo
     EOF

Một vài toán tử khác ( >&-, x>&y x<&y) có thể được sử dụng để đóng hoặc sao chép mô tả tệp. Để biết chi tiết về chúng, vui lòng xem phần có liên quan trong hướng dẫn sử dụng của bạn ( ví dụ ở đây là bash).

Điều đó chỉ bao gồm các toán tử phổ biến nhất của shell giống Bourne. Một số shell có một vài toán tử chuyển hướng bổ sung của riêng chúng.

Ksh, bash và zsh cũng có cấu trúc <(…), >(…)=(…)(cái sau zshchỉ có một). Đây không phải là chuyển hướng, nhưng thay thế quá trình .


2
Có lẽ đáng lưu ý rằng không phải tất cả các shell đều bằng nhau, và đặc biệt làm nổi bật các tính năng đặc trưng của bash.
Greg Hewgill

1
@GregHewgill yeah, tôi đã từ bỏ nó bằng cách nói rằng tôi đang thảo luận về sự tôn trọng bash. Điều này đang được chuẩn bị như một câu hỏi và trả lời kinh điển để đóng các câu hỏi "Điều kỳ lạ này làm gì" và hầu hết chúng là từ những người sử dụng bash. Tôi hy vọng người khác sẽ tham gia và trả lời cho các vỏ không bash, nhưng làm nổi bật những cái cụ thể của bash có rất nhiều ý nghĩa. Tôi sẽ phải kiểm tra mặc dù, tôi không biết chúng ở trên đỉnh đầu tôi.
terdon

&>, >>><<<tất cả đều không phải là posix như là tài liệu tham khảo cho các ký tự không chỉ chữ và số trong tên của tài liệu ở đây. Câu trả lời này cũng thảo luận rất ít về cách chúng hoạt động - ví dụ, việc nói về một lệnh đơn giản và một lệnh mà không giải thích được chúng là gì và vỏ quyết định như thế nào là điều tồi tệ hơn .
mikeerv

@mikeerv cảm ơn. Họ làm việc trên bash và zsh mặc dù. Tôi không biết những gì, nếu có bất cứ điều gì, thực sự cụ thể trong danh sách đó. Tôi nên xem qua phần này và thêm các shell mỗi tác phẩm vào nhưng điều đó sẽ liên quan đến việc tìm hiểu trước.
terdon

1
@ Arc676 Không, họ không đánh giá là đúng hay sai, đó là một bối cảnh hoàn toàn khác. Điều này chỉ có nghĩa là giá trị thoát là 0 chỉ ra một vấn đề (không phải false) và mã thoát là 0 biểu thị thành công (không true). Đó luôn là cách và khá chuẩn. Mã thoát không 0 chỉ ra lỗi trong mọi môi trường tôi biết.
terdon

60

Cảnh báo về '>'

Những người mới bắt đầu Unix mới tìm hiểu về chuyển hướng I / O ( <>) thường thử những thứ như

lệnh ... input_file > the_same_file

hoặc là

chỉ huy < file      > the_same_file

hoặc, gần như tương đương,

tập tin mèo | chỉ huy > the_same_file

( grep, sed, cut, sort, Và spelllà ví dụ về các lệnh mà mọi người đang bị cám dỗ để sử dụng trong các cấu trúc như thế này.) Người dùng có ngạc nhiên khi khám phá ra rằng những tình huống dẫn đến tập tin trở nên trống rỗng.

Một sắc thái dường như không được đề cập trong câu trả lời khác có thể được tìm thấy ẩn trong câu đầu tiên của phần Chuyển hướng của bash (1) :

Trước khi một lệnh được thực thi, đầu vào và đầu ra của nó có thể được chuyển hướng bằng cách sử dụng một ký hiệu đặc biệt được giải thích bởi shell.

Năm từ đầu tiên phải được in đậm, in nghiêng, gạch chân, phóng to, nhấp nháy, tô màu đỏ và được đánh dấu bằng một dấu chấm than trong hình tam giác màu đỏbiểu tượng, để nhấn mạnh thực tế là trình bao thực hiện (các) chuyển hướng được yêu cầu trước khi lệnh được thực thi . Và cũng nhớ

Chuyển hướng đầu ra làm cho tập tin được mở ra để viết tập tin. Nếu tập tin không tồn tại, nó được tạo ra; nếu nó tồn tại, nó bị cắt cụt về kích thước không.

  1. Vì vậy, trong ví dụ này:

    sort roster > roster

    Shell mở rostertệp để ghi, cắt bớt nó (nghĩa là loại bỏ tất cả nội dung của nó), trước khi sortchương trình bắt đầu chạy. Đương nhiên, không có gì có thể được thực hiện để phục hồi dữ liệu.

  2. Người ta có thể ngây thơ mong đợi rằng

    tr "[:upper:]" "[:lower:]" < poem > poem

    có thể tốt hơn Vì shell xử lý các chuyển hướng từ trái sang phải, nó sẽ mở ra poemđể đọc (đối với trđầu vào tiêu chuẩn) trước khi mở nó để ghi (cho đầu ra tiêu chuẩn). Nhưng nó không giúp được gì. Mặc dù chuỗi thao tác này mang lại hai xử lý tệp, cả hai đều trỏ đến cùng một tệp. Khi shell mở tệp để đọc, nội dung vẫn ở đó, nhưng chúng vẫn bị ghi đè trước khi chương trình được thực thi. 

Vậy giờ làm gì với nó?

Các giải pháp bao gồm:

  • Kiểm tra xem chương trình bạn đang chạy có khả năng, nội bộ, riêng để xác định nơi đầu ra đi không. Điều này thường được chỉ định bởi một -o(hoặc --output=) mã thông báo. Đặc biệt,

    sort roster -o roster

    gần tương đương với

    sort roster > roster

    ngoại trừ, trong trường hợp đầu tiên, sortchương trình mở tệp đầu ra. Và nó đủ thông minh để không mở tệp đầu ra cho đến khi nó đã đọc tất cả (các) tệp đầu vào.

    Tương tự như vậy, ít nhất là một số phiên bản của sedcó một -i(chỉnh sửa i n đặt) tùy chọn có thể được sử dụng để viết các đầu ra trở ra đến tập tin đầu vào (một lần nữa, sau khi tất cả các đầu vào đã được đọc). Biên tập như ed/ ex, emacs, pico, và vi/ vim cho phép người dùng chỉnh sửa một tập tin văn bản và lưu văn bản chỉnh sửa trong file gốc. Lưu ý rằng ed(ít nhất) có thể được sử dụng không tương tác.

    • vicó một tính năng liên quan. Nếu bạn gõ , nó sẽ ghi nội dung của bộ đệm chỉnh sửa ra , đọc đầu ra và chèn nó vào bộ đệm (thay thế nội dung ban đầu).:%!commandEntercommand
  • Đơn giản mà hiệu quả:

    lệnh ... input_file > temp_file   && mv temp_file  input_file

    Điều này có nhược điểm là, nếu input_filelà một liên kết, nó (có thể) sẽ được thay thế bằng một tệp riêng. Ngoài ra, tập tin mới sẽ thuộc sở hữu của bạn, với sự bảo vệ mặc định. Đặc biệt, điều này mang đến rủi ro rằng tập tin sẽ trở nên dễ đọc trên thế giới, ngay cả khi bản gốc input_filekhông có.

    Biến thể:

    • commandinput_file > temp_file && cp temp_file input_file && rm temp_file
      mà vẫn sẽ (có khả năng) rời khỏi temp_filethế giới có thể đọc được. Thậm chí còn tốt hơn:
    • cp input_file temp_file && commandtemp_file > input_file && rm temp_file
      Chúng bảo vệ trạng thái liên kết, chủ sở hữu và chế độ (bảo vệ) của tệp, có khả năng với chi phí gấp đôi I / O. (Bạn có thể cần sử dụng một tùy chọn như -ahoặc -pbật cp để nói với nó để bảo toàn các thuộc tính.)
    • commandinput_file > temp_file &&
      cp --attributes-only --preserve=all input_file temp_file &&
      mv temp_file input_file
      (được chia thành các dòng riêng biệt để dễ đọc) Điều này duy trì chế độ của tệp (và, nếu bạn là chủ sở hữu), nhưng làm cho nó thuộc sở hữu của bạn (nếu bạn không root) và làm cho nó mới, tập tin riêng biệt.
  • Blog này (Chỉnh sửa các tập tin tại chỗ của EDT) gợi ý và giải thích

    {rm input_file   && ra   lệnh > input_file ; } < input_file

    Điều này đòi hỏi phải commandcó khả năng xử lý đầu vào tiêu chuẩn (nhưng hầu như tất cả các bộ lọc đều có thể). Bản thân blog gọi đây là một loại bùn nguy hiểm và không khuyến khích sử dụng nó. Và điều này cũng sẽ tạo một tệp mới, riêng biệt (không được liên kết với bất cứ thứ gì), thuộc sở hữu của bạn và với các quyền mặc định.

  • Gói moreutils có một lệnh gọi là sponge:

    lệnh ... input_file | bọt biển the_same_file

    Xem câu trả lời này để biết thêm thông tin.

Đây là một cái gì đó làm tôi ngạc nhiên hoàn toàn: cú pháp nói :

[Hầu hết các giải pháp này] sẽ thất bại trên hệ thống tệp chỉ đọc, trong đó, chỉ đọc có nghĩa là có nghĩa là bạn $HOME sẽ có thể ghi được, nhưng /tmpsẽ chỉ đọc (theo mặc định). Chẳng hạn, nếu bạn có Ubuntu và bạn đã khởi động vào Recovery Console, đây thường là trường hợp. Ngoài ra, toán tử tài liệu ở đây <<<cũng sẽ không hoạt động ở đó, vì nó yêu cầu /tmpphải đọc / ghi vì nó cũng sẽ ghi một tệp tạm thời vào đó.
(xem câu hỏi này bao gồm straceđầu ra 'd)

Sau đây có thể làm việc trong trường hợp đó:

  • Đối với người dùng cao cấp duy nhất: Nếu lệnh của bạn được đảm bảo để sản xuất cùng một lượng dữ liệu đầu ra là có đầu vào (ví dụ sort, hoặc tr không có các -dhoặc -stùy chọn), bạn có thể thử
    lệnh ... input_file | dd of = the_same_file conv = notrunc
    Xem câu trả lời nàycâu trả lời này để biết thêm thông tin, bao gồm giải thích ở trên và các lựa chọn thay thế hoạt động nếu lệnh của bạn được đảm bảo tạo ra cùng một lượng dữ liệu đầu ra như có đầu vào hoặc ít hơn (ví dụ grep, hoặc cut). Những câu trả lời này có lợi thế là chúng không yêu cầu bất kỳ không gian trống nào (hoặc chúng yêu cầu rất ít). Các câu trả lời ở trên của biểu mẫu yêu cầu rõ ràng rằng có đủ không gian trống để hệ thống có thể giữ đồng thời toàn bộ tệp đầu vào (cũ) và tệp đầu ra (mới); điều này không rõ ràng đúng với hầu hết các giải pháp khác (ví dụ, và ). Ngoại lệ: có thể sẽ cần nhiều không gian trống, bởi vìcommandinput_file > temp_file && …sed -ispongesort … | dd …sort cần phải đọc tất cả đầu vào của nó trước khi nó có thể ghi bất kỳ đầu ra nào và có lẽ nó sẽ đệm hầu hết nếu không phải tất cả dữ liệu đó trong một tệp tạm thời.
  • Chỉ dành cho người dùng nâng cao:
    lệnh  vào input_file 1 <> the_same_file
    có thể tương đương với ddcâu trả lời, ở trên. Các cú pháp mở file có tên trên bộ mô tả tập tin cho cả đầu vào và đầu ra , mà không cần cắt bỏ nó - loại kết hợp và . Lưu ý: Một số chương trình (ví dụ và ) có thể từ chối chạy trong kịch bản này vì chúng có thể phát hiện ra rằng đầu vào và đầu ra là cùng một tệp. Xem câu trả lời này để thảo luận về vấn đề trên và tập lệnh làm cho câu trả lời này hoạt động nếu lệnh của bạn được đảm bảo tạo ra cùng một lượng dữ liệu đầu ra như có đầu vào hoặc ít hơn . Cảnh báo: Tôi chưa kiểm tra kịch bản của Peter, vì vậy tôi không đảm bảo cho kịch bản đó.n<> filen n<n>catgrep

Vì vậy, câu hỏi là gì?

Đây là một chủ đề phổ biến trên U & L; nó được giải quyết trong các câu hỏi sau:

Nhiều thứ và không tính Super User hay hỏi Ubuntu. Tôi đã kết hợp rất nhiều thông tin từ câu trả lời cho các câu hỏi trên ở đây trong câu trả lời này, nhưng không phải tất cả. (Tức là, để biết thêm thông tin, hãy đọc các câu hỏi được liệt kê ở trên và câu trả lời của họ.)

PS Tôi không có liên kết với blog mà tôi đã trích dẫn, ở trên.


Vì câu hỏi này tiếp tục được đưa ra, tôi nghĩ rằng tôi sẽ thử viết một câu trả lời kinh điển của Google. Tôi có nên đăng nó ở đây (và có thể liên kết với nó từ một số câu hỏi bị buôn bán nặng nề hơn), hay tôi nên chuyển nó sang một trong những câu hỏi thực sự đặt ra vấn đề này? Ngoài ra, đây có phải là một tình huống mà các câu hỏi nên được hợp nhất?
Scott

/ tmp Một thư mục được tạo sẵn cho các ứng dụng cần một nơi để tạo các tệp tạm thời. Các ứng dụng sẽ được phép tạo các tệp trong thư mục này, nhưng không cho rằng các tệp đó được bảo tồn giữa các yêu cầu của ứng dụng.
mikeerv

@mikeerv: Vâng, (1) Tôi đang trích dẫn cú pháp và (2) Tôi đã nói rằng tôi rất ngạc nhiên. Tôi nghĩ rằng, nếu bất cứ điều gì sẽ được đọc-viết, nó sẽ được /tmp.
Scott

Chà, điều mà @syntaxerror nói đôi khi rất kỳ lạ bởi vì, theo tôi nghĩ, dashnó sẽ là trình phục hồi mặc định trên Ubuntu và nó không chỉ không hiểu về sự <<<di truyền mà còn có các đường dẫn ẩn danh cho <<di truyền và không gây rối ${TMPDIR:-/tmp}cho điều đó mục đích nào cả. Xem cái này hoặc cái này để xem các bản demo ở đây - xử lý tài liệu. Ngoài ra tại sao cùng một lượng đầu ra hoặc ít cảnh báo?
mikeserv

@mikeserv: Vâng, dd … conv=notrunc1<>câu trả lời không bao giờ cắt các tập tin đầu ra, vì vậy, nếu đầu ra của lệnh này là ít hơn so với đầu vào (ví dụ grep), sẽ có một số byte của bản gốc còn sót lại ở phần cuối của tập tin. Và, nếu đầu ra lớn hơn đầu vào (ví dụ cat -n, nlhoặc (khả năng) grep -n), có một nguy cơ ghi đè lên dữ liệu cũ trước khi bạn đọc nó.
Scott

29

Nhiều quan sát trên ;, &, ()

  • Lưu ý rằng một số lệnh trong câu trả lời của terdon có thể là null. Ví dụ, bạn có thể nói

    command1 ;

    (không có command2). Điều này tương đương với

    command1

    (nghĩa là, nó chỉ đơn giản là chạy command1ở phía trước và chờ cho nó hoàn thành.

    command1 &

    (không có command2) sẽ khởi chạy command1trong nền và sau đó đưa ra dấu nhắc shell khác ngay lập tức.

  • Ngược lại, command1 &&, command1 ||, và command1 |không thực hiện bất kỳ ý nghĩa. Nếu bạn gõ một trong số này, shell sẽ (có thể) cho rằng lệnh được tiếp tục trên một dòng khác. Nó sẽ hiển thị dấu nhắc shell thứ cấp (tiếp tục), thường được đặt thành >và tiếp tục đọc. Trong một kịch bản shell, nó sẽ chỉ đọc dòng tiếp theo và nối nó với những gì nó đã đọc. (Coi chừng: đây có thể không phải là điều bạn muốn xảy ra.)

    Lưu ý: một số phiên bản của một số shell có thể coi các lệnh không hoàn chỉnh đó là lỗi. Trong các trường hợp như vậy (hoặc, trên thực tế, trong bất kỳ trường hợp nào bạn có lệnh dài), bạn có thể đặt dấu gạch chéo ngược ( \) ở cuối dòng để báo cho trình bao tiếp tục đọc lệnh trên dòng khác:

    command1  &&  \
    command2

    hoặc là

    find starting-directory -mindepth 3 -maxdepth 5 -iname "*.some_extension" -type f \
                            -newer some_existing_file -user fred -readable -print
  • Như terdon nói, ()có thể được sử dụng để nhóm các lệnh. Tuyên bố rằng họ là những người không thực sự có liên quan đến cuộc thảo luận đó. Một số lệnh trong câu trả lời của terdon có thể là các nhóm lệnh . Ví dụ,

    ( command1 ; command2 )  &&  ( command3; command4 )

    thực hiện điều này:

    • Chạy command1và đợi cho nó kết thúc.
    • Sau đó, bất kể kết quả của việc chạy lệnh đầu tiên đó là gì, hãy chạy command2và đợi cho đến khi kết thúc.
    • Sau đó, nếu command2thành công,

      • Chạy command3và đợi cho nó kết thúc.
      • Sau đó, bất kể kết quả của việc chạy lệnh đó là gì, hãy chạy command4và đợi cho nó kết thúc.

      Nếu command2thất bại, dừng xử lý dòng lệnh.

  • Dấu ngoặc bên ngoài, |liên kết rất chặt chẽ, vì vậy

    command1 | command2 || command3

    tương đương với

    ( command1 | command2 )  ||  command3

    &&||ràng buộc chặt chẽ hơn ;, vì vậy

    command1 && command2 ; command3

    tương đương với

    ( command1 && command2 ) ;  command3

    tức là, command3sẽ được thực thi bất kể trạng thái thoát của command1và / hoặc command2.


Hoàn hảo, +1! Tôi nói họ không liên quan vì tôi không muốn đi sâu vào chi tiết đó. Tôi muốn có một câu trả lời có thể hoạt động như một chiếc áo choàng nhanh cho những người mới, những người đang tự hỏi tất cả những tiếng cười khúc khích kỳ lạ ở cuối các lệnh khác nhau là gì. Tôi không có ý ám chỉ chúng không hữu ích. Cảm ơn đã thêm tất cả điều này.
terdon

1
Tôi lo ngại về vấn đề "khối lượng quan trọng" - nếu chúng tôi đăng mọi thứ mà chúng tôi có thể nói về đạn pháo, chúng tôi sẽ kết thúc với phiên bản TL; DR của Sổ tay Tham khảo Bash.
G-Man

Cũng đáng đề cập: Không giống như trong các ngôn ngữ của họ C, ;bản thân nó (hoặc không có lệnh trước nó) là một lỗi cú pháp và không phải là một câu lệnh trống. Như vậy ; ;là một lỗi. (Một cạm bẫy phổ biến cho người dùng mới, IMHO). Ngoài ra: ;;là một dấu phân cách đặc biệt, cho các casebáo cáo.
muru

1
@muru: Điểm tốt, nhưng hãy khái quát nó. Bất kỳ của các nhà khai thác kiểm soát có thể xuất hiện giữa các lệnh: ;, &&, ||, &, và |, những sai sót nếu chúng xuất hiện mà không có gì trước họ. Ngoài ra, terdon đã giải quyết ;;(một cách ngắn gọn) trong câu trả lời của mình.
G-Man

1
@Wildcard: OK, tôi thấy bạn đến từ đâu. Từ khóa là "có thể"; tất cả những gì tôi đã nói là tôi không đảm bảo rằng tất cả các shell sẽ chấp nhận các cấu trúc như vậy (ví dụ, YMMV). Rõ ràng tôi đã viết điều đó trước khi tôi biết về việc sử dụng linebreakmã thông báo trong ngữ pháp vỏ POSIX. Vì vậy, có lẽ thật an toàn khi nói rằng tất cả các vỏ tuân thủ POSIX sẽ chấp nhận chúng. Tôi đứng trước tuyên bố của tôi như một tuyên bố từ chối trách nhiệm chung; nếu bạn tìm thấy một vỏ POSIX đủ cũ, chẳng hạn như vỏ Bourne thực tế hoặc cũ hơn, tất cả các cược đều bị tắt.
G-Man
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.