Satu baris dengan 2 file tmp (bukan yang Anda inginkan) adalah:
foo | bar > file1.txt && baz | quux > file2.txt && diff file1.txt file2.txt
Dengan bash , Anda dapat mencoba:
diff <(foo | bar) <(baz | quux)
foo | bar | diff - <(baz | quux) # or only use process substitution once
Versi ke-2 akan lebih jelas mengingatkan Anda input mana yang, dengan menunjukkan
-- /dev/stdin
vs. ++ /dev/fd/63
atau sesuatu, bukan dua fds bernomor.
Bahkan pipa bernama tidak akan muncul di sistem file, setidaknya pada OS di mana bash dapat mengimplementasikan substitusi proses dengan menggunakan nama file seperti /dev/fd/63
untuk mendapatkan nama file yang dapat dibuka dan dibaca oleh perintah untuk benar-benar membaca dari deskriptor file yang sudah terbuka yang diatur oleh bash set sebelum menjalankan perintah. (Yaitu bash menggunakan pipe(2)
sebelum garpu, dan kemudian dup2
untuk mengalihkan dari output quux
ke deskripsi file input untukdiff
, pada fd 63.)
Pada sistem tanpa "ajaib" /dev/fd
atau /proc/self/fd
, bash mungkin menggunakan pipa bernama untuk mengimplementasikan substitusi proses, tetapi setidaknya akan mengelolanya sendiri, tidak seperti file sementara, dan data Anda tidak akan ditulis ke sistem file.
Anda dapat memeriksa bagaimana bash mengimplementasikan proses substitusi dengan echo <(true)
mencetak nama file alih-alih membacanya. Mencetak /dev/fd/63
pada sistem Linux yang khas. Atau untuk detail lebih lanjut tentang apa tepatnya panggilan sistem yang digunakan bash, perintah ini pada sistem Linux akan melacak panggilan sistem dan file-deskriptor panggilan
strace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
Tanpa bash, Anda bisa membuat pipa bernama . Gunakan -
untuk memberi tahu diff
untuk membaca satu input dari STDIN, dan menggunakan pipa bernama sebagai yang lain:
mkfifo file1_pipe.txt
foo|bar > file1_pipe.txt && baz | quux | diff file1_pipe.txt - && rm file1_pipe.txt
Perhatikan bahwa Anda hanya dapat menyalurkan satu output ke beberapa input dengan perintah tee:
ls *.txt | tee /dev/tty txtlist.txt
Perintah di atas menampilkan output dari ls * .txt ke terminal dan outputnya ke file teks txtlist.txt.
Tetapi dengan substitusi proses, Anda dapat menggunakan tee
untuk memberi makan data yang sama ke beberapa saluran pipa:
cat *.txt | tee >(foo | bar > result1.txt) >(baz | quux > result2.txt) | foobar
mkfifo a; cmd >a& cmd2|diff a -; rm a
pipeline1 | diff -u - <(pipeline2)
. Maka output akan lebih jelas mengingatkan Anda input mana yang, dengan menunjukkan-- /dev/stdin
vs.++ /dev/fd/67
atau sesuatu, bukan dua fds bernomor.foo <( pipe )
) tidak mengubah sistem file. Pipa itu anonim ; tidak memiliki nama di sistem file . Shell menggunakanpipe
system call untuk membuatnya, bukanmkfifo
. Gunakanstrace -f -efile,desc,clone,execve bash -c '/bin/true | diff -u - <(/bin/true)'
untuk melacak panggilan sistem dan file-deskriptor sistem jika Anda ingin melihatnya sendiri. Di Linux,/dev/fd/63
adalah bagian dari/proc
sistem file virtual; secara otomatis memiliki entri untuk setiap deskriptor file, dan itu bukan salinan konten. Jadi Anda tidak dapat menyebutnya "file sementara" kecualifoo 3<bar.txt
diperhitungkanDalam bash Anda dapat menggunakan subkulit, untuk mengeksekusi pipa perintah secara terpisah, dengan melampirkan pipa dalam tanda kurung. Anda kemudian dapat mengawali ini dengan <untuk membuat pipa bernama anonim yang kemudian dapat Anda lewatkan ke diff.
Sebagai contoh:
Pipa bernama anonim dikelola oleh bash sehingga mereka dibuat dan dihancurkan secara otomatis (tidak seperti file sementara).
sumber
Beberapa orang yang tiba di halaman ini mungkin mencari diff baris-demi-baris, untuk yang mana
comm
ataugrep -f
harus digunakan.Satu hal yang perlu diperhatikan adalah bahwa, dalam semua contoh jawaban, perbedaan tidak akan benar-benar dimulai sampai kedua aliran selesai. Uji ini dengan misalnya:
Jika ini merupakan masalah, Anda bisa mencoba sd (stream diff), yang tidak memerlukan pengurutan (seperti
comm
halnya) atau memproses substitusi seperti contoh di atas, apakah pesanan atau besarnya lebih cepat darigrep -f
dan mendukung aliran yang tak terbatas.Contoh tes yang saya usulkan akan ditulis seperti ini di
sd
:Tetapi perbedaannya adalah bahwa
seq 100
akan dibedakan denganseq 10
segera. Perhatikan bahwa, jika salah satu stream adalah atail -f
, diff tidak dapat dilakukan dengan substitusi proses.Berikut adalah blogpost yang saya tulis tentang perbedaan aliran pada terminal, yang memperkenalkan
sd
.sumber