Di 'che ho troppi programmi a
e b
che posso eseguire con ./a
e ./b
.
È possibile differenziare i loro output senza prima scrivere su file temporanei?
Di 'che ho troppi programmi a
e b
che posso eseguire con ./a
e ./b
.
È possibile differenziare i loro output senza prima scrivere su file temporanei?
Risposte:
Utilizzare <(command)
per passare l'output di un comando a un altro programma come se fosse un nome file. Bash invia l'output del programma a una pipe e passa un nome di file simile /dev/fd/63
al comando esterno.
diff <(./a) <(./b)
Allo stesso modo puoi usare >(command)
se vuoi inserire qualcosa in un comando.
Questo si chiama "Sostituzione del processo" nella pagina man di Bash.
-bash: syntax error near unexpected token ('
. Ho provato di nuovo senza parentesi e ho ottenuto -bash: java: No such file or directory
. Non funziona se il comando ha parametri?
alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'
. (Quindi per esempio: diffcmd "ls" "ls -a").
fseek
, zsh offre =(./a)
che può essere usato in modo identico <(./a)
ma utilizza un file temporaneo sotto il cofano, che zsh eliminerà per te.)
Aggiungendo a entrambe le risposte, se si desidera vedere un confronto affiancato, utilizzare vimdiff
:
vimdiff <(./a) <(./b)
Qualcosa come questo:
vimdiff
crea viste di confronto delle differenze belle, intelligenti e interattive. Sembra venire con il vim
pacchetto sulla maggior parte dei sistemi.
vimdiff
mostra anche non solo la linea che differisce, ma anche il frammento di testo specifico che differisce.
Un'opzione sarebbe quella di utilizzare le pipe denominate (FIFO) :
mkfifo a_fifo b_fifo
./a > a_fifo &
./b > b_fifo &
diff a_fifo b_fifo
... ma la soluzione di John Kugelman è molto più pulita.
rm a_fifo b_fifo
.
Per chiunque sia curioso, questo è il modo in cui esegui la sostituzione del processo usando la shell di pesce :
bash:
diff <(./a) <(./b)
Pesce:
diff (./a | psub) (./b | psub)
Purtroppo l'implementazione nei pesci è attualmente carente ; fish si bloccherà o utilizzerà un file temporaneo sul disco. Inoltre, non è possibile utilizzare psub per l'output del comando.
Aggiungendo un po 'di più alle già buone risposte (mi ha aiutato!):
Il comando docker
fornisce il suo aiuto a STD_ERR
(cioè il descrittore di file 2)
Volevo vedere se docker attach
e ho docker attach --help
dato lo stesso risultato
$ docker attach
$ docker attach --help
Dopo aver digitato quei due comandi, ho fatto quanto segue:
$ diff <(!-2 2>&1) <(!! 2>&1)
!! è lo stesso di! -1 che significa eseguire il comando 1 prima di questo - l'ultimo comando
! -2 significa eseguire il comando due prima di questo
2> & 1 significa inviare output file_descriptor 2 (STD_ERR) nello stesso posto dell'output file_descriptor 1 (STD_OUT)
Spero che questo sia stato di qualche utilità.
Per zsh, l'utilizzo =(command)
crea automaticamente un file temporaneo e lo sostituisce =(command)
con il percorso del file stesso. Con la normale sostituzione del processo, $(command)
viene sostituito con l' output del comando.
Questa funzione zsh è molto utile e può essere utilizzata in questo modo per confrontare l'output di due comandi utilizzando uno strumento diff, ad esempio Beyond Compare:
bcomp =(ulimit -Sa | sort) =(ulimit -Ha | sort)
Per Beyond Compare, tenere presente che è necessario utilizzare bcomp
quanto sopra (anziché bcompare
) poiché bcomp
avvia il confronto e attende il completamento. Se lo usi bcompare
, questo avvia il confronto ed esce immediatamente a causa della quale scompaiono i file temporanei creati per memorizzare l'output dei comandi.
Maggiori informazioni qui: http://zsh.sourceforge.net/Intro/intro_7.html
Notare anche questo:
Si noti che la shell crea un file temporaneo e lo elimina al termine del comando.
e la seguente che è la differenza tra $(...)
e =(...)
:
Se leggi la pagina man di zsh, potresti notare che <(...) è un'altra forma di sostituzione del processo che è simile a = (...). C'è una differenza importante tra i due. Nel caso <(...), la shell crea una pipe denominata (FIFO) anziché un file. Questo è meglio, dal momento che non riempie il file system; ma non funziona in tutti i casi. In effetti, se avessimo sostituito = (...) con <(...) negli esempi sopra, tutti avrebbero smesso di funzionare tranne fgrep -f <(...). Non è possibile modificare una pipe o aprirla come una cartella di posta; fgrep, tuttavia, non ha problemi a leggere un elenco di parole da una pipe. Potresti chiederti perché la barra diff <(foo) non funziona, poiché foo | diff - bar funziona; questo perché diff crea un file temporaneo se nota che uno dei suoi argomenti è -, quindi copia l'input standard nel file temporaneo.