Come può l'input standard di un programma passare come arg ad un altro?


17

Diciamo che esiste un programma, che accetta due argomenti; file di input e file di output.

Che cosa succede se non desidero salvare questo file di output su disco, ma piuttosto passarlo direttamente a stdinun altro programma. C'è un modo per raggiungere questo obiettivo?

Molti comandi che trovo su Linux forniscono un'opzione per passare "-" come argomento del file di output, che fa ciò che ho specificato sopra. Questo perché passare stdinun programma come argomento non è possibile? Se lo è, come lo facciamo?

Un esempio di come immaginerei di usare questo è:

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

La shell che sto usando è bash.


1
cat <file | cmd /dev/fd/0funziona sulla maggior parte dei computer.
Mikeserv,

Non funziona per me. Provato con: cat < README.txt | cp /dev/fd/0. Dicevacp: missing destination file operand after ‘/dev/fd/0’ Try 'cp --help' for more information.
Dziugas il

1
program input-file /dev/stdout | another-program? Si noti inoltre che echonon legge nulla dallo stdin.
Yaegashi,

1
@Dziugas - ovviamente no - non è possibile cpun file da nessuna parte. echo 1 2 3| cp /dev/fd/0 /dev/ttystamperà 1 2 3. A proposito, /dev/fd/[num]è più probabile che funzioni rispetto /dev/std(in|out|err)alla maggior parte dei casi. Vedi la portabilità dei collegamenti descrittori di file su cosa puoi aspettarti di lavorare dove.
Mikeserv,

1
Un buon programma UNIX scriverebbe sullo standard output lasciando all'utente la possibilità di decidere se desidera reindirizzare a un file o pipe ad un altro comando.
Jorge Bucaran,

Risposte:


13

Se il programma supporta la scrittura su qualsiasi descrittore di file anche se non è possibile cercarlo, è possibile utilizzarlo /dev/stdoutcome file di output. Questo è un link simbolico al /proc/self/fd/1mio sistema. Il descrittore di file 1 è stdout.


Questo ha risolto la mia domanda. Quindi non c'è modo di farlo quando il programma deve cercare?
Dziugas,

3
Se stai cercando di impedire l'accesso al disco, puoi scrivere il file in / dev / shm /, tuttavia, se non vuoi alcun file sul filesystem, allora per quanto ne so, non c'è modo di cercare una pipa. Cercare in avanti significa che dovrebbe bufferizzare tutto in memoria fino a quando non ha raggiunto quel punto in avanti, e cercare all'indietro implica aver bufferizzato tutto in memoria.
TiCPU,

pdftotextcome molte altre utilità (ma non tutte) supportano -anche questo (che funzionerebbe anche su sistemi che non supportano / dev / stdout, o dove / dev / stdout non funzionano come previsto come su Linux dove stdout non è una pipa). pdftotext file.pdf - | wc -c
Stéphane Chazelas,

11

Dalla pdftotextpagina man:

Se il file di testo è ´- ', il testo viene inviato a stdout.

Quindi in questo caso tutto ciò che serve è:

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

O se vuoi reindirizzare questo a STDIN di un altro programma:

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

L'uso -come sostituto di un nome file è una convenzione che molte utility seguono (incluso pdftotext) quando vogliamo l'input da STDIN o l'output a STDOUT. Tuttavia, non tutte le utility seguono questa convenzione. In tal caso, il modo idiomatico di farlo in bash è usare una sostituzione di processo :

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

Qui il >( ) comporta in gran parte come un file passato my_utility, ma invece di essere un file reale, il flusso viene reindirizzato nello stdin del processo contenuto, ovvero cat. Quindi qui, il testo dovrebbe alla fine produrre come richiesto.

L'uso di catquasi sempre fa scattare le suonerie di allarme UUOC su forum come questo. Io sostengo che se l'utilità non supporta -, allora questo è un uso utile di cat, anche se ci sono modi per fare questo processo di sostituzione senza il cat, allora sono tutto orecchie ;-).

Tuttavia, se (come afferma la domanda) la destinazione finale dello stream è STDIN di un altro programma, allora catpuò essere eliminato:

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

2
E fammi tornare indietro ancora una volta: se prog2scrive su stdout, è meglio di , perché il modulo attende il completamento (cioè, prima che la shell emetta il prossimo prompt o passa al comando successivo (ad esempio, dopo o )), mentre il -less form attende solo il completamento. Inoltre, dopo il modulo, è lo stato di uscita da , mentre, nell'altro, è lo stato di uscita da . (Paghi i tuoi soldi e fai la tua scelta.)prog1 input_file >( cat ) | prog2prog1 input_file >( prog2 )catprog2;&&catprog1cat$?prog2$?prog1
Scott,

4

Se la tua shell li supporta, il modo più semplice di fare tali manipolazioni sarebbe usare la sostituzione del processo : <(…)e >(…). Funziona con bash, zsh e ksh e possibilmente con altre shell. Per esempio:

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

Tuttavia, questo non aiuta nell'esempio che dichiari poiché pdftotextverrà salvato in un file di testo. Mentre la tua scelta migliore (a parte quella ovvia dell'uso -) è quella di usare /dev/stdoutcome suggerito da @TiCPU, puoi anche usare un'altra funzione di shell. Il costrutto si !:Nriferisce all'ennesimo argomento del comando precedente. Pertanto, potresti fare:

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

1
Mentre sono d'accordo che cat <()può essere utile in alcune situazioni, in questo scenario tuttavia non funziona affatto. Il problema (molto male descritto da OP, devo ammetterlo) è che pdftotextaccetta due argomenti: file di input e file di output . Se manca il secondo argomento, non produce nulla, quindi cat <(pdftotext "file.pdf")non restituirebbe nulla. Si può ingannare il pdftotextcomando dando >(cat)come secondo argomento come ha risposto Digital Trauma, ma cat <()qui è inutile. Ovviamente nel pdftotextcaso sia meglio usare solo -come nome del file di output.
Jimmij,

1
@Scott Come è la mia risposta un UUOC? Come faresti questo processo di sostituzione senza gatto? >( )collegherà efficacemente il flusso a qualsiasi processo sia all'interno, quindi in realtà abbiamo bisogno di un catqui per generare quel flusso. Normalmente dovremmo essere in grado di fare qualcosa del genere pdftotext input.pdf -, ma a quanto pare pdftotextnon supporta il -parametro per l'output diretto su stdout invece di un file - provalo.
Digital Trauma,

1
@DigitalTrauma non è eccezionale. Credo che cat sia il più veloce che puoi ottenere in caso di stampa, ma in realtà puoi usare altri comandi >(grep something)per essere più utile. A proposito, il mio pdftotext 3.04 do sostegno -come un file di output, quindi sono un po 'sorpreso da tutta la discussione.
jimmij,

1
@terdon Odio essere un pignolo, ma questo non sembra funzionare. In particolare non è diverso da quello in esecuzione pdftotext "C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.pdf", che inserisce l'output in un file chiamato C BY BRIAN W KERNIGHAN & DENNIS M RITCHIE.txt, ma nessuno del testo viene inviato a STDOUT per il piping a un altro programma.
Trauma digitale,

1
@DigitalTrauma che non è un pignolo! Sono io che sono un idiota. Grazie per averlo segnalato e per favore non scusarti mai quando fai notare errori. Preferirei di gran lunga farmi notare il mio errore e quindi imparare qualcosa piuttosto che lasciarlo lì in tutta la sua dubbia gloria.
terdon

-2
cmd tty

ttyrestituisce il nome del terminale a cui è collegato stdout.


Non sono sicuro di come questo risponda alla domanda, che riguarda la combinazione di comandi; forse ti espandi con un esempio di come lo raggiungeresti.
Dhag,

Immagino tu stia dicendo di verificare con ttyil nome del terminale e quindi usare quel file come output, ad esempio pdftotext file.pdf /dev/pts/2. In tal caso, sono d'accordo.
Jimmij,

Che può essere abbreviato / automatizzato ; che sarà generalmente equivalente a . Ma questo approccio presuppone che l'obiettivo sia quello di mostrare l'output di (cioè, nel terminale), e non è quello che la domanda sta ponendo (vedere i commenti sulla risposta di Terdon per alcuni chiarimenti sul significato della domanda). prog1  input_file $(tty)prog1  input_file /dev/ttyprog1
Scott,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.