Làm thế nào đầu vào tiêu chuẩn của một chương trình có thể được chuyển qua làm đối số cho một chương trình khác?


17

Giả sử một chương trình tồn tại, trong đó có hai đối số; tập tin đầu vào và tập tin đầu ra.

Điều gì sẽ xảy ra nếu tôi không muốn lưu tệp đầu ra này vào đĩa, nhưng chuyển thẳng sang stdinchương trình khác. Có cách nào để đạt được điều này?

Rất nhiều lệnh tôi gặp trên Linux cung cấp tùy chọn để vượt qua '-' làm đối số tệp đầu ra, thực hiện những gì tôi đã chỉ định ở trên. Đây có phải là vì việc thông qua stdinmột chương trình như là một đối số là không thể? Nếu có, làm thế nào để chúng ta làm điều đó?

Một ví dụ về cách tôi sẽ hình ảnh bằng cách sử dụng này là:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" stdin(echo)

Vỏ tôi đang sử dụng là bash.


1
cat <file | cmd /dev/fd/0hoạt động trên hầu hết các đơn vị.
mikeerv 20/07/2015

Không làm việc cho tôi. Đã thử nó với : cat < README.txt | cp /dev/fd/0. Nó nóicp: missing destination file operand after ‘/dev/fd/0’ Try 'cp --help' for more information.
Dziugas 20/07/2015

1
program input-file /dev/stdout | another-program? Cũng lưu ý rằng echokhông đọc gì từ stdin.
yaegashi 20/07/2015

1
@Dziugas - tất nhiên là không - bạn không thể cplà một tập tin. echo 1 2 3| cp /dev/fd/0 /dev/ttysẽ in 1 2 3. Và nhân tiện, /dev/fd/[num]có nhiều khả năng làm việc hơn /dev/std(in|out|err)trong hầu hết các trường hợp. Xem Tính di động của Liên kết mô tả tệp về những gì bạn có thể mong đợi để làm việc ở đâu.
mikeerv 20/07/2015

1
Một chương trình UNIX tốt sẽ ghi vào đầu ra tiêu chuẩn để người dùng quyết định xem họ có muốn chuyển hướng đến một tệp hoặc đường ống sang lệnh khác hay không.
Jorge Bucaran

Câu trả lời:


13

Nếu chương trình hỗ trợ ghi vào bất kỳ mô tả tệp nào ngay cả khi không thể tìm kiếm, bạn có thể sử dụng /dev/stdoutlàm tệp đầu ra. Đây là một liên kết tượng trưng đến /proc/self/fd/1trên hệ thống của tôi. Mô tả tập tin 1 là thiết bị xuất chuẩn.


Điều này đã giải quyết câu hỏi của tôi. Vì vậy, không có cách nào để làm điều đó khi chương trình cần tìm kiếm?
Dziugas 20/07/2015

3
Nếu bạn đang cố gắng ngăn chặn truy cập đĩa, bạn có thể ghi tệp vào / dev / shm /, tuy nhiên, nếu bạn không muốn bất kỳ tệp nào trên hệ thống tệp, thì theo tôi biết, không có cách nào để tìm kiếm một đường ống. Tìm kiếm về phía trước có nghĩa là nó sẽ phải đệm mọi thứ trong bộ nhớ cho đến khi đạt được điểm đó về phía trước và tìm kiếm lùi có nghĩa là đã đệm mọi thứ trong bộ nhớ.
TiCPU

pdftotextgiống như nhiều (nhưng không phải tất cả) các tiện ích khác cũng hỗ trợ -cho điều đó (sẽ hoạt động ngay cả trên các hệ thống không hỗ trợ / dev / stdout hoặc nơi / dev / stdout không hoạt động như mong đợi trên Linux, nơi stdout không hoạt động một đường ống). pdftotext file.pdf - | wc -c
Stéphane Chazelas

11

Từ pdftotexttrang người đàn ông:

Nếu tệp văn bản là-', văn bản được gửi đến thiết bị xuất chuẩn.

Vì vậy, trong trường hợp này, tất cả những gì bạn cần là:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" -

Hoặc nếu bạn muốn chuyển cái này sang STDIN của một chương trình khác:

pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" - | another_prog

Sử dụng -thay thế cho tên tệp là một quy ước, nhiều tiện ích tuân theo (bao gồm pdftotext) khi chúng tôi muốn nhập từ STDIN hoặc xuất ra STDOUT. Tuy nhiên không phải tất cả các tiện ích đều tuân theo quy ước này. Trong trường hợp đó, cách thành ngữ để làm điều này trong bash là sử dụng thay thế quy trình :

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( cat )

Ở đây, các >( )hành vi phần lớn giống như một tệp được truyền đến my_utility, nhưng thay vì là một tệp thực, luồng được truyền vào stdin của quy trình được chứa, tức là mèo. Vì vậy, ở đây, văn bản cuối cùng nên xuất theo yêu cầu.

Việc sử dụng cathầu như luôn luôn đặt chuông báo thức UUOC trên các diễn đàn như thế này. Tôi cho rằng nếu tiện ích không hỗ trợ -, thì đây là cách sử dụng hữu ích cat, mặc dù nếu có bất kỳ cách nào để thực hiện thay thế quy trình này mà không có cat, thì tôi đều là tai ;-).

Tuy nhiên, nếu (như câu hỏi nêu) đích đến cuối cùng của luồng là STDIN của một chương trình khác, thì catcó thể loại bỏ:

my_utility "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf" >( another_prog )

2
Và hãy để tôi backpedal một lần nữa: nếu prog2ghi vào thiết bị xuất chuẩn, tốt hơn là bởi vì biểu mẫu chờ hoàn thành (nghĩa là trước khi shell phát ra dấu nhắc tiếp theo hoặc chuyển sang lệnh tiếp theo (ví dụ: sau hoặc )), trong khi hình thức không chờ đợi chỉ để hoàn thành. Ngoài ra, sau biểu mẫu, là trạng thái thoát khỏi , trong khi đó, trong trạng thái khác, là trạng thái thoát khỏi . (Bạn trả tiền và bạn chọn lựa.)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
Scott

4

Nếu hệ vỏ của bạn hỗ trợ chúng, cách đơn giản nhất để thực hiện các thao tác đó sẽ là sử dụng thay thế quy trình : <(…)>(…). Điều này hoạt động trong bash, zsh và ksh và có thể các shell khác. Ví dụ:

$ sort <(printf "b\nc\na\n")
a
b
c
$ ls
foo
$ cp <(find . -name foo) bar
$ ls
bar  foo

Tuy nhiên, điều này sẽ không giúp ích trong ví dụ bạn nêu vì pdftotextsẽ lưu trong tệp văn bản. Mặc dù lựa chọn tốt nhất của bạn (ngoài việc sử dụng rõ ràng -) là sử dụng /dev/stdouttheo đề xuất của @TiCPU, bạn cũng có thể sử dụng một tính năng shell khác. Cấu trúc !:Nđề cập đến đối số N của lệnh trước đó. Do đó, bạn có thể làm:

$ pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf"  out.txt
$ cat !:2

1
Mặc dù tôi đồng ý rằng cat <()có thể hữu ích trong một số tình huống, nhưng trong trường hợp này, tuy nhiên nó không hoạt động. Vấn đề (được mô tả rất kém bởi OP, tôi phải thừa nhận) là pdftotextcó hai đối số: tệp đầu vàotệp đầu ra . Nếu đối số thứ hai bị thiếu thì nó không tạo ra gì, do đó cat <(pdftotext "file.pdf")cũng sẽ không trả về gì. Người ta có thể gian lận pdftotextmệnh lệnh bằng cách đưa ra >(cat)như một đối số thứ hai như Digital Trauma đã trả lời, nhưng cat <()ở đây là vô nghĩa. Rõ ràng trong pdftotexttrường hợp tốt nhất chỉ nên sử dụng -làm tên tệp đầu ra.
jimmij 20/07/2015

1
@Scott Làm thế nào là câu trả lời của tôi một UUOC? Làm thế nào bạn sẽ làm quá trình này thay thế mà không có con mèo? >( )sẽ dẫn luồng một cách hiệu quả vào bất kỳ quy trình nào bên trong - vì vậy chúng tôi thực sự cần một catluồng ở đây để xuất luồng đó. Thông thường chúng ta sẽ có thể làm một cái gì đó như pdftotext input.pdf -, nhưng dường như pdftotextkhông hỗ trợ -tham số để xuất trực tiếp ra thiết bị xuất chuẩn thay vì tệp - hãy thử nó.
Chấn thương kỹ thuật số

1
@DigitalTrauma nó không phải là uuoc. Tôi tin rằng mèo là cách nhanh nhất bạn có thể nhận được trong trường hợp chỉ in, nhưng thực tế bạn có thể sử dụng lệnh khác >(grep something)để hữu ích hơn. BTW, tôi pdftotext 3.04 làm hỗ trợ -như một tập tin đầu ra, vì vậy tôi là một chút ngạc nhiên bởi toàn bộ cuộc thảo luận.
jimmij 20/07/2015

1
@terdon Tôi ghét trở thành một stickler, nhưng điều này dường như không hoạt động. Cụ thể, không khác gì chạy pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf", nó đặt đầu ra trong một tệp được gọi C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txt, nhưng không có văn bản nào được xuất thành STDOUT để chuyển sang chương trình khác.
Chấn thương kỹ thuật số

1
@DigitalTrauma không phải là một stickler! Đó là tôi là một thằng ngốc. Cảm ơn đã chỉ ra và xin đừng bao giờ xin lỗi khi chỉ ra sai lầm. Tôi thà để sai lầm của mình chỉ ra cho tôi và vì vậy học được điều gì đó hơn là để nó ở đó trong tất cả vinh quang đáng ngờ của nó.
terdon

-2
cmd tty

ttytrả về tên của thiết bị đầu cuối được kết nối với stdout.


Tôi không chắc cách này trả lời câu hỏi, đó là về cách kết hợp các lệnh; có lẽ bạn mở rộng với một ví dụ về cách bạn sẽ đạt được điều đó.
dhag 20/07/2015

Tôi đoán bạn đang nói để kiểm tra với ttytên của thiết bị đầu cuối, và sau đó sử dụng tệp đó làm đầu ra, ví dụ pdftotext file.pdf /dev/pts/2. Trong trường hợp đó, tôi đồng ý.
jimmij 20/07/2015

Điều đó có thể được viết tắt / tự động để ; mà thường sẽ tương đương với . Nhưng cách tiếp cận này giả định rằng mục tiêu là hiển thị đầu ra của (nghĩa là trong thiết bị đầu cuối), và đó không phải là câu hỏi đang hỏi (xem các nhận xét về câu trả lời của terdon để biết rõ hơn về ý nghĩa của câu hỏi). prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
Scott
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.