Output diff dari dua program tanpa file sementara

Jawaban:

211

Gunakan <(command)untuk meneruskan output satu perintah ke program lain seolah-olah itu adalah nama file. Bash mem-pipe hasil program ke pipa dan meneruskan nama file seperti /dev/fd/63ke perintah luar.

diff <(./a) <(./b)

Demikian pula Anda dapat menggunakan >(command)jika Anda ingin menyalurkan sesuatu ke perintah.

Ini disebut "Substitusi Proses" di halaman manual Bash.

John Kugelman
sumber
1
Satu kekurangan yang perlu diperhatikan adalah bahwa jika ./a atau ./b gagal, penelepon tidak akan mengetahui hal itu.
Alexander Pogrebnyak
5
OP memang menandai bash pertanyaan, tetapi sebagai catatan, ini tidak berfungsi di shell lain. Ini adalah ekstensi bash ke standar utilitas Posix.
DigitalRoss
5
Saya mencoba solusi ini dengan program Java dan mendapat kesalahan ini: -bash: syntax error near unexpected token ('. Saya mencoba lagi tanpa tanda kurung dan mendapat -bash: java: No such file or directory. Apakah tidak berfungsi jika perintah memiliki parameter?
styfle
1
@DigitalRoss - Solusi ini dapat diperluas ke shell lain menggunakan alias. Dalam tcsh, keburukan berikut bekerja: alias diffcmd bash -c \'diff \<\(sh -c \!:1\) \<\( sh -c \!:2 \)\'. (Kemudian untuk, contoh: diffcmd "ls" "ls -a").
Paul Lynch
Bagi siapa pun yang berkeliaran di luar Google, ini juga berfungsi di bawah zsh. (Juga, jika Anda perlu memasukkan input ke dalam sesuatu yang memanggil fseek, zsh menawarkan =(./a)yang dapat digunakan secara identik dengan <(./a)tetapi menggunakan file sementara di bawah tenda, yang akan dihapus zsh untuk Anda.)
ssokolow
26

Menambah kedua jawaban, jika Anda ingin melihat perbandingan berdampingan, gunakan vimdiff:

vimdiff <(./a) <(./b)

Sesuatu seperti ini:

masukkan deskripsi gambar di sini

patah kaki
sumber
vimdiffmenciptakan tampilan perbandingan perbedaan yang indah, cerdas dan interaktif. Tampaknya datang dengan vimpaket pada kebanyakan sistem.
Tim Visée
vimdiffjuga menunjukkan tidak hanya garis yang berbeda tetapi juga fragmen teks tertentu yang berbeda.
Anton Tarasenko
20

Salah satu opsi adalah menggunakan pipa bernama (FIFO) :

mkfifo a_fifo b_fifo
./a > a_fifo &
./b > b_fifo &
diff a_fifo b_fifo

... tapi solusi John Kugelman jauh lebih bersih.

martin clayton
sumber
Anda sebaiknya menghapus pipa yang dinamai setelah menggunakannya, dengan rm a_fifo b_fifo.
Franklin Yu
15

Bagi siapa pun yang penasaran, ini adalah bagaimana Anda melakukan proses substitusi dalam menggunakan kerang Ikan :

Pesta:

diff <(./a) <(./b)

Ikan:

diff (./a | psub) (./b | psub)

Sayangnya implementasi pada ikan saat ini kurang ; fish akan menggantung atau menggunakan file sementara pada disk. Anda juga tidak dapat menggunakan psub untuk output dari perintah Anda.

James McMahon
sumber
Ini saat ini tidak bekerja dengan benar pada ikan. Jika output dari program lebih besar dari satu BUFSIZ, perintah akan hang. (atau ikan sebenarnya hanya akan menggunakan file sementara pada disk)
Evan Benn
7

Menambahkan sedikit lebih banyak ke jawaban yang sudah baik (membantu saya!):

Perintah dockermenampilkan bantuannya ke STD_ERR(yaitu file deskriptor 2)

Saya ingin melihat apakah docker attachdan docker attach --helpmemberikan hasil yang sama

$ docker attach

$ docker attach --help

Setelah mengetik kedua perintah itu, saya melakukan yang berikut:

$ diff <(!-2 2>&1) <(!! 2>&1)

!! sama dengan! -1 yang berarti menjalankan perintah 1 sebelum ini - perintah terakhir

! -2 Berarti jalankan perintah dua sebelum yang ini

2> & 1 berarti mengirim output file_descriptor 2 (STD_ERR) ke tempat yang sama dengan output file_descriptor 1 (STD_OUT)

Semoga ini bermanfaat.

darrenthatcher
sumber
0

Untuk zsh, menggunakan =(command)secara otomatis membuat file sementara dan menggantikan =(command)dengan jalur file itu sendiri. Dengan Substitusi Proses normal, $(command)diganti dengan output dari perintah.

Fitur zsh ini sangat berguna dan dapat digunakan seperti itu untuk membandingkan output dari dua perintah menggunakan alat diff, misalnya Beyond Compare:

bcomp  =(ulimit -Sa | sort) =(ulimit -Ha | sort)

Untuk Beyond Compare, perhatikan bahwa Anda harus menggunakan bcompuntuk yang di atas (bukan bcompare) sejak bcompmeluncurkan perbandingan dan menunggu untuk menyelesaikan. Jika Anda menggunakan bcompare, itu meluncurkan perbandingan dan segera keluar karena file sementara yang dibuat untuk menyimpan output dari perintah menghilang.

Baca lebih lanjut di sini: http://zsh.sourceforge.net/Intro/intro_7.html

Perhatikan juga ini:

Perhatikan bahwa shell membuat file sementara, dan menghapusnya ketika perintah selesai.

dan berikut ini yang merupakan perbedaan antara $(...)dan =(...):

Jika Anda membaca halaman manual zsh, Anda mungkin memperhatikan bahwa <(...) adalah bentuk lain dari proses substitusi yang mirip dengan = (...). Ada perbedaan penting antara keduanya. Dalam kasus <(...), shell membuat pipa bernama (FIFO) alih-alih file. Ini lebih baik, karena tidak mengisi sistem file; tetapi tidak bekerja dalam semua kasus. Bahkan, jika kita telah mengganti = (...) dengan <(...) pada contoh di atas, semuanya akan berhenti bekerja kecuali untuk fgrep -f <(...). Anda tidak dapat mengedit pipa, atau membukanya sebagai folder surat; Namun, fgrep tidak memiliki masalah dengan membaca daftar kata-kata dari sebuah pipa. Anda mungkin bertanya-tanya mengapa bilah diff <(foo) tidak berfungsi, karena foo | karya diff-bar; ini karena diff membuat file sementara jika memperhatikan bahwa salah satu argumennya adalah -, dan kemudian menyalin input standarnya ke file sementara.

Ashutosh Jindal
sumber