Chuyển hướng đầu ra từ tất cả các lệnh đến tập tin, không chỉ cuối cùng


11

Tôi muốn thêm một tiêu đề vào một tệp có tiếng vang, sau đó sử dụng một lệnh để tạo phần còn lại của tệp. Điều này có nghĩa là tôi sẽ sử dụng hai lệnh riêng biệt.

Làm cách nào để ghi đầu ra từ cả hai lệnh vào một tệp có chuyển hướng?

Tôi đã thử

echo "header line" | cut -c 1-5 input_file > output_file

echo "header line"; cut -c 1-5 input_file > output_file

Điều này chỉ chuyển hướng đầu ra từ lệnh cắt.

Lệnh sau hoạt động, nhưng cảm thấy vụng về:

echo "header line" > output_file; cut -c 1-5 input_file >> output_file

Cách thông minh để giải quyết vấn đề của tôi là gì?

Câu trả lời:


11

Vấn đề ở đây không phải là vấn đề với chuyển hướng Linux; đúng hơn, đó là một sự hiểu lầm cơ bản về cách thức hoạt động của đường ống. Chuyển hướng ở đây không hoạt động vì chỉ cắt thực sự in ra thiết bị xuất chuẩn. thiết bị xuất chuẩn cho lệnh echo đã được chuyển sang cắt stdin (không được sử dụng trong trường hợp này vì tệp được chỉ định).

echo "header line" > output_file && cut -c 1-5 input_file >> output_file

là những gì bạn muốn và hoàn toàn không phù hợp (Tôi đã thay thế ;bằng &&lệnh cắt để chỉ thực hiện nếu tiêu đề được viết thành công; cách này sẽ không thực thi nếu bạn không có quyền tạo hoặc ghi vào output_file ).

Bạn cũng có thể làm tất cả trong một subshell, ví dụ.

(echo "header line"; cut -c 1-5 input_file) > output_file

nhưng không có lợi ích thực sự khi làm điều này và với các ví dụ phức tạp hơn, nó có thể gây ra vấn đề nếu bạn không quen với cách lớp vỏ được phân chia.

Nếu bạn muốn cắt để chuyển stdin qua stdout, bạn có thể thử:

echo "header line" | cut -c 1-5 - input_file

(Dấu gạch ngang là lối tắt phổ biến cho stdin)

Tuy nhiên, điều này cũng sẽ thực hiện thao tác cắt trên stdin (dẫn đến một dòng tiêu đề của "tiêu đề"). Thật khó để nói đây có phải là điều bạn muốn hay không từ câu hỏi.


13

Những gì bạn tìm kiếm là:

{ echo "header line"; cut -c 1-5 input_file; } > output_file
  • Cú pháp này không có tác dụng phụ vì các lệnh được thực thi trong trình bao hiện tại, không phải là một lớp con
  • Có một sự phân định rõ ràng về các lệnh đi đến output_file
  • Nó có quy mô tốt như bạn có thể viết lại theo cách đó:

{
  echo "header line"
  cut -c 1-5 input_file
  ... # insert new commands here
} > output_file

Nếu bạn muốn đầu ra lỗi đi đến cùng một tệp, bạn có thể sửa đổi dòng cuối cùng theo cách đó:

} > output_file 2>&1

Cảm ơn Olivier Dulac đã nhắc nhở mẹo đó.

Nếu bạn muốn một số đầu ra bên trong khối đi đến màn hình của mình, bạn có thể sử dụng cú pháp đó:

{
  echo "header line"
  echo "this line doesn't go to output_file" > /dev/tty
  cut -c 1-5 input_file
} > output_file

+1: rõ ràng hơn và xác định rõ ràng những gì được chuyển hướng ở đâu. Để chuyển hướng tất cả mọi thứ (bao gồm msg lỗi): { .... } > some_file 2>&1(sẽ "clobber" some_file không clobber, nhưng append để nó thay vào đó, chỉ cần thay đổi. >Thành một >>: { ... } >> some_file 2>&1)
Olivier Dulac

4

Chỉ cần làm tròn các câu trả lời là có exec.

exec > output_file
echo "header line"
cut -c 1-5 input_file

+1: trong các tập lệnh, nó rất phổ biến để sử dụng điều này (ít hơn trên dòng lệnh, vì mọi thứ bắt đầu khó hiểu ^^)
Olivier Dulac

Ai đó có thể giải thích về giải pháp này? Tôi có thể thấy những gì nó đang làm, nhưng tôi không hiểu 'exec' trong bối cảnh này. Ngoài ra, có vẻ như một cái gì đó bạn phải tắt một lần nữa nếu phần còn lại của tập lệnh của bạn cần thiết bị xuất chuẩn bình thường.
Joe

1
Khi bạn sử dụng exec trong script mà không có lệnh, bạn có thể thực hiện chuyển hướng I / O trên exec mà ảnh hưởng đến shell hiện tại và tất cả các con tương lai.
hildred

Cảm ơn. Tôi chưa từng thấy điều đó trước đây. Tôi nghĩ nó sẽ rất hữu ích.
Joe
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.