Làm thế nào để `>` và `>>` hoạt động?


9

Tôi đã cố gắng để revmột tập tin và sau đó chuyển nó đến cat > same_filenhưng nó đang chuyển thành một tập tin trống.

Trong khi tôi đã thử rev file.txt | cat > file2.txt && mv file.txt file2.txt;nó làm việc.

Thậm chí rev file.txt | cat >> file.txt;đã làm việc.

Nhưng khi tôi thử rev file.txt | cat > file.txtnó đã thất bại.


Bạn cũng có thể bỏ catđi như thế này : rev file.txt > file2.txt && mv file2.txt file.txt. Đây là một sử dụng thừacat . Bằng cách để nó ra, bạn dự phòng thêm một quá trình.
chiến lược

Câu trả lời:


19

Điều cơ bản bạn cần nắm bắt trong trường hợp này giữa cả hai cách chuyển hướng (> và >>) là:

>

Chuyển hướng và ghi đè thông tin nơi nó được trỏ đến. Điều này xảy ra trong khi nhận được bất kỳ thông tin nào qua đường ống "|"

>>

Chuyển hướng và nối với thông tin mà nó được trỏ đến. Điều này xảy ra trong khi nhận được bất kỳ thông tin nào qua đường ống "|"

Trong cả hai trường hợp nếu tập tin không tồn tại, nó sẽ được tạo thay thế. Chỉ trên ">>" thông tin sẽ được nối nếu bạn chạy lại trên cùng một tệp. Với ">" bạn chỉ cần ghi đè lên mọi thứ bạn đã làm trong lần chạy đầu tiên.

Nhưng đây là thỏa thuận khi sử dụng cùng một tệp đầu vào như tệp đầu ra. Trong trường hợp cụ thể đó, nếu bạn sử dụng ">", bạn sẽ xóa thông tin mà phần "đầu vào" cần phân tích, vì tệp đầu ra sẽ là "ghi đè lên nó". Vì vậy, trong:

rev file.txt | cat > file.txt

Điều thực sự xảy ra trong "giải thích chuyển động chậm" là:

  1. revchuẩn bị đảo ngược nội dung file.txtvà gửi nó đến đường ống
  2. Trong khi revđang gửi thông tin đến đường ống, đường ống truyền trực tiếp đến cat.
  3. Trong khi catnhận được thông tin, nó sẽ tự động áp dụng nó cho thông tin file.txtđược đặt.
  4. Từ khóa ở đây là "while", bởi vì mọi thứ đang diễn ra cùng một lúc. Xin vui lòng xem các ý kiến ​​tuyệt vời dưới đây của Emil để hiểu sâu hơn về phần này.
  5. catsẽ không chờ đợi revđể ống toàn bộ tập tin. Nó chỉ đơn giản là bắt đầu ngay khi phần đầu tiên của thông tin được gửi đến, điều đó có nghĩa, tùy thuộc vào biểu tượng bạn đã sử dụng, nó sẽ mở ra một kết nối file.txt.
  6. Trong trường hợp này vì bạn đã sử dụng > thay vì >> , trình bao sẽ cắt bớt tệp đầu ra, điều đó có nghĩa là nó sẽ mở và xóa thông tin file.txttrong khi chờ thông tin mới đến. Với >> nó sẽ mở một kết nối với file.txtvà chờ thông tin mới trên dòng cuối cùng được phát hiện.
  7. Kể từ khi thông tin đã được xóa trong file.txtvới > , revsẽ cố gắng để làm điều đó của công việc và nhận được gì vì cattất cả mọi thứ bị xóa để chuẩn bị cho những thông tin mới.

Vậy tại sao những người khác làm việc sau khi đọc những điều trên. Vì điều này:

rev file.txt | cat > file2.txt && mv file.txt file2.txt

Ở đây bạn đang dẫn đến con mèo đang gửi thông tin đến một tập tin khác . Trong trường hợp này, tệp đầu vào được xử lý file.txtkhông giống với tệp đầu ra file2.txt. Sau đó bạn đang theo nghĩa đen ghi đè lên toàn bộ file2.txtvới file.txt, vì vậy tất cả các quá trình được thực hiện bởi catđã bị xóa. Về cơ bản, toàn bộ dòng có thể được đơn giản hóa như thế cp file.txt file2.txtbởi vì nó đang làm điều tương tự vì file2.txtcuối cùng nó mất revvà được ghi đè bằng mvlệnh.

rev file.txt | cat >> file.txt

Trong trường hợp này, bạn đang nối thông tin vào cùng một tệp. Vì vậy, nó chỉ mở một kết nối đến tập tin đó nhưng không xóa thông tin như đã thấy với một > . Kết quả cuối cùng phải là, thông tin gốc cộng với thông tin đảo ngược.


5
Các tập tin không bị cắt bởi con mèo. Nó bị cắt bởi shell, trước khi bất kỳ lệnh nào trong đường ống thậm chí được bắt đầu.
Emil Jeřábek

Chính xác, đã tìm kiếm những từ dễ dàng hơn để giải thích. Vì hơi khó để giải thích nếu OP không biết nó là cái gì và tất cả những thứ đó. Cố gắng làm cho nó "thân thiện" nhất có thể.
Luis Alvarado

1
Chà, thực sự không quan trọng là nó được thực hiện bởi vỏ, nhưng thời gian bạn trình bày là sai. Việc cắt ngắn sẽ không xảy ra ở bước 6, nhưng ở bước 0. rev file.txt | cat --bogus-option > file.txtcũng sẽ cắt bớt tệp, mặc dù con mèo sẽ không cố mở nó.
Emil Jeřábek

@ EmilJeřábek bạn đúng. Những người dùng vẫn không biết nó hoạt động như thế nào sẽ dễ dàng hơn nếu chúng ta đi từng bước chỉ với các lệnh. Ngoài ra, ví dụ của bạn vẫn đang gửi thông tin vào cùng một tệp, vì vậy bash sẽ đọc toàn bộ dòng đó, xem đầu ra và vẫn mở VÀ cắt bớt nó. Lỗi chỉ đơn giản là stderr xuất ra thiết bị xuất chuẩn.
Luis Alvarado

4
Xem thêm moreutils , một bộ công cụ tuyệt vời (có sẵn từ kho lưu trữ gói moreutils), bao gồm sponge, một công cụ được thiết kế dành riêng cho việc ghi đè lên một tệp đầu vào. Ví dụ, rev file.txt >file2.txt && mv file2.txt file.txtcách giải quyết sẽ trở thành rev file.txt | sponge file.txt, nó sẽ hoạt động chính xác ngay cả khi đã có một cái gì đó được đặt tên file2.txt.
Daniel Wagner

9

Khi shell thấy chuyển hướng, nó sẽ mở các tệp có liên quan trước, trước khi thực hiện bất kỳ lệnh nào liên quan. Do đó, khi bạn làm:

foo file.txt | bar > file.txt

Chuyển hướng để file.txtlàm cho nó bị cắt ngắn trước khi foo chạy và có thể đọc file.txt. Bên cạnh đó, đây là lý do tại sao bạn không thể làm:

sed 'blah' file.txt > file.txt

Và tại sao sedcó một tùy chọn chỉnh sửa tại chỗ.

Cuối cùng, làm:

.. | cat > file.txt

một cách sử dụng mèo vô dụng , đặc biệt là nếu bạn đang cố đọc từ file.txttrước đó.

Nếu bạn muốn đảo ngược một tập tin tại chỗ, không có phím tắt . Bạn có thể sử dụng sedhoặc các awkthủ thuật với chỉnh sửa tại chỗ.


3

>là một bộ chuyển hướng (toán tử) gửi đầu ra đến một thứ khác
(đầu vào của lệnh tiếp theo, máy in ..)

Trong trường hợp của bạn, đầu ra đi đến một tệp file.txt, nếu tệp này đã tồn tại, nó sẽ bị ghi đè, nếu không nó được tạo.

>>là một toán tử chắp thêm, nếu file.txtđã tồn tại, đầu ra được nối vào cuối tệp. nếu tệp không tồn tại thì nó được tạo và đầu ra được ghi vào tệp mới, giống như >(redirector).


OP dường như đã hiểu điều này. Sự nhầm lẫn dường như chỉ xuất phát từ cùng một tệp nằm ở cả hai phía của toán tử >>>toán tử.
bzlm

0

Bạn có thể sử dụng Vim trong chế độ Ex:

ex -sc '%!rev' -cx file.txt
  1. % chọn tất cả các dòng

  2. ! chạy lệnh

  3. x lưu và đó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.