Tại sao việc chuyển hướng đầu ra của một tệp thành chính nó tạo ra một tệp trống?


17

Tại sao việc chuyển hướng đầu ra của một tệp thành chính nó tạo ra một tệp trống?

Nói ở Bash, tại sao

less foo.txt > foo.txt

fold foo.txt > foo.txt

sản xuất một sản phẩm nào foo.txt? Vì một phụ lục như less eggs.py >> eggs.py tạo ra hai bản sao của văn bản trong eggs.py, người ta có thể mong đợi rằng một ghi đè sẽ tạo ra một bản sao của văn bản.

Lưu ý, tôi không nói đây là một lỗi, nhiều khả năng nó là một con trỏ đến một cái gì đó sâu sắc về Unix.

Câu trả lời:


18

Khi bạn sử dụng >, tệp được mở trong chế độ cắt ngắn để nội dung của nó bị xóa trước khi lệnh cố đọc nó.

Khi bạn sử dụng >>, tệp được mở ở chế độ chắp thêm để dữ liệu hiện có được giữ nguyên. Tuy nhiên, vẫn còn khá rủi ro khi sử dụng cùng một tệp với đầu vào và đầu ra trong trường hợp này. Nếu tệp đủ lớn để không vừa với kích thước bộ đệm đầu vào đọc, kích thước của nó có thể tăng vô hạn cho đến khi hệ thống tệp đầy (hoặc đạt được hạn ngạch đĩa của bạn).

Nếu bạn muốn sử dụng một tệp cả đầu vào và đầu ra với một lệnh không hỗ trợ sửa đổi vị trí, bạn có thể sử dụng một vài cách giải quyết:

  • Sử dụng tệp trung gian và ghi đè lên tệp gốc khi hoàn tất và chỉ khi không có lỗi xảy ra trong khi chạy tiện ích (đây là cách an toàn và phổ biến nhất).

    fold foo.txt > fold.txt.$$ && mv fold.txt.$$ foo.txt
    
  • Tránh các tập tin trung gian với chi phí mất dữ liệu một phần hoặc toàn bộ nếu xảy ra lỗi hoặc gián đoạn. Trong ví dụ này, nội dung của foo.txt được chuyển làm đầu vào cho một subshell (bên trong dấu ngoặc đơn) trước các tập tin bị xóa. Các nút trước đó vẫn tồn tại khi lớp con giữ cho nó mở trong khi đọc dữ liệu. Các tập tin được viết bởi các tiện ích bên trong (ở đây fold ) trong khi có cùng tên ( foo.txt ) trỏ đến một nút khác vì mục nhập thư mục cũ đã bị xóa vì vậy về mặt kỹ thuật, có hai "tệp" khác nhau có cùng tên trong quá trình. Khi lớp con kết thúc, inode cũ được giải phóng và dữ liệu của nó bị mất. Cẩn thận để đảm bảo bạn có đủ dung lượng để tạm thời lưu trữ cả tệp cũ và tệp mới cùng một lúc nếu không bạn sẽ mất dữ liệu.

    (rm foo.txt; fold > foo.txt) < foo.txt
    

3
sponge từ nhiều hơn cũng có thể giúp đỡ fold foo.txt | sponge foo.txt - hoặc là fold foo.txt | sponge !$ cũng nên làm.
slhck

@slhck Thật vậy, bọt biển cũng có thể làm công việc này. Tuy nhiên, không được chỉ định bởi POSIX cũng như dòng chính trong Unix như HĐH, nên không có khả năng có mặt.
jlliagre

Nó không giống như nó không thể thực hiện hiện tại mặc dù;)
slhck

7

Tệp được mở để ghi bởi shell trước khi ứng dụng có cơ hội đọc nó. Mở tập tin để viết cắt ngắn 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.