Dash'te Süreç Değişimi nasıl taklit edilir?


18

İçinde bash, süreç değiştirme kullanın ve bir diske kaydedilmiş bir dosya gibi bir işlem çıktısını tedavi:

$ echo <(ls)
/dev/fd/63

$ ls -lAhF <(ls)
lr-x------ 1 root root 64 Sep 17 12:55 /dev/fd/63 -> pipe:[1652825]

maalesef, Süreç Yedeği desteklenmiyor dash.

Kısa sürede taklit etmenin en iyi yolu ne olurdu Process Substitution?

Çıkışı bir yere geçici bir dosya olarak kaydetmek istemiyorum ( /tmp/) ve sonra silmek zorundayım. Alternatif bir yol var mı?


Ne yapmaya çalıştığınıza bağlı olarak boruları kullanabilirsiniz.
— Eric Renouf

Dürüst olmak gerekirse, taşınabilirlik ana endişeniz değilse bash, cihazınıza yüklemek daha kolay olmaz mıydı ?
— Arkadiusz Drabczyk

1
Ödül bildiriminde verdiğiniz örnek, bu bağlantılı cevabın konusudur . Orada gösterildiği gibi, Gilles'in cevabının basitleştirilmiş bir versiyonu ( yerine /dev/fdkullanılabilirliği ve kullanımı varsayarak ) olabilir . xz -cd <file>cat <file> | xz -dxz -cd "$1" | { xz -cd "$2" | { diff /dev/fd/3 /dev/fd/4; } 3<&0; } 4<&0
— fra-san

1
@ fra-san - aslında ihtiyacım olan buydu. İsterseniz cevaplayabilirsiniz. Teşekkürler.
— Martin Vegter

Yanıtlar:


4

Mevcut ödül bildirimindeki soru:

genel örnek çok karmaşıktır. Birisi lütfen aşağıdaki örneğin nasıl uygulanacağını açıklayabilir mi?diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)

burada bir cevap var gibi görünüyor .

Gilles'in cevabında gösterildiği gibi , genel fikir, "üretici" komutlarının çıktısını , bir boru hattının farklı aşamalarında yeni cihaz dosyalarına ( 1) göndermek ve bunları, dosya adlarını bağımsız değişken olarak alabilecekleri "tüketici" komutları için kullanılabilir hale getirmektir ( sisteminizin size dosya tanımlayıcılarına erişim izni verdiği varsayılarak /dev/fd/X)

Aradığınızı elde etmenin en basit yolu muhtemelen:

xz -cd file1.xz | { xz -cd file2.xz | diff /dev/fd/3 -; } 3<&0

(Kullanma file1.xzyerine "$1"okunabilmesi için ve xz -cdyerine cat ... | xz -dtek bir komut yeterli olduğu için).

Birinci "üretici" komutunun çıktısı, xz -cd file1.xzbir bileşik komutuna ( {...}) bağlanır ; ancak, bir sonraki komutun standart girdisi olarak hemen tüketilmek yerine, dosya tanımlayıcısına çoğaltılır3 ve böylece bileşik komutunun içindeki her şeye erişilebilir olur /dev/fd/3. xz -cd file2.xzNe standart girdisini ne de dosya tanımlayıcısından herhangi bir şeyi tüketmeyen ikinci "üretici" komutunun çıktısı 3, daha sonra diffstandart girdisinden ve okunan "tüketici" komutuna bağlanır /dev/fd/3.

Borulama ve dosya tanımlayıcı çoğaltması, gerektiği kadar "üretici" komutu için aygıt dosyaları sağlamak amacıyla eklenebilir, örn:

xz -cd file1.xz | { xz -cd file2.xz | { diff /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0

Sorunuz bağlamında alakasız olsa da, şunu belirtmek gerekir:

  1. cmd1 <(cmd2) <(cmd3), cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0Ve ( cmd2 | ( cmd3 | ( cmd1 /dev/fd/3 /dev/fd/4 ) 4<&0 ) 3<&0 )ilk yürütme ortamında farklı potansiyel etkileri vardır.

  2. Olur aksine cmd1 <(cmd2) <(cmd3), cmd3ve cmd1de cmd2 | { cmd3 | { cmd1 /dev/fd/3 /dev/fd/4; } 4<&0; } 3<&0kullanıcıdan herhangi bir giriş okumak mümkün olmayacaktır. Bunun için daha fazla dosya tanımlayıcı gerekir. Örneğin,

    diff <(echo foo) <(read var; echo "$var")
    

    gibi bir şeye ihtiyacın olacak

    { echo foo | { read var 0<&9; echo "$var" | diff /dev/fd/3 -; } 3<&0; } 9<&0
    

1 Bunlarla ilgili daha fazla bilgiyi U&L'de bulabilirsiniz, örn. Anlama / dev ve alt dizinleri ve dosyaları .


12

Sıhhi tesisatı manuel olarak yaparak kabuğun kaputun altında ne yaptığını çoğaltabilirsiniz. Sisteminizde girişler varsa, dosya tanımlayıcı karıştırma özelliğini kullanabilirsiniz:/dev/fd/NNN

main_command <(produce_arg1) <(produce_arg2) >(consume_arg3) >(consume_arg4)

için

{ produce_arg1 |
  { produce_arg2 |
    { main_command /dev/fd5 /dev/fd6 /dev/fd3 /dev/fd4 </dev/fd/8 >/dev/fd/9; } 5<&0 3>&1 |
    consume_arg3; } 6<&0 4>&1; |
  consume_arg4; } 8<&0 9>&1

Birden çok girişi ve çıkışı göstermek için daha karmaşık bir örnek gösterdim. Standart girdiden okumanız gerekmiyorsa ve işlem ikamesini kullanmanızın tek nedeni, komutun açık bir dosya adı gerektirmesidir, şunları kullanabilirsiniz /dev/stdin:

main_command <(produce_arg1)
produce_arg1 | main_command /dev/stdin

Olmadan , adlandırılmış bir boru kullanmanız gerekir . Adlandırılmış bir kanal bir dizin girdisidir, bu nedenle bir yerde geçici bir dosya oluşturmanız gerekir, ancak bu dosya yalnızca bir addır, veri içermez./dev/fd/NNN

tmp=$(mktemp -d)
mkfifo "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
produce_arg1 >"$tmp/f1" &
produce_arg2 >"$tmp/f2" &
consume_arg3 <"$tmp/f3" &
consume_arg4 <"$tmp/f4" &
main_command "$tmp/f1" "$tmp/f2" "$tmp/f3" "$tmp/f4"
rm -r "$tmp"

2
</dev/fd/8 >/dev/fd/9<&8 >&9Linux'takine eşdeğer değildir ve bundan kaçınılmalıdır.
— Stéphane Chazelas

@Gilles - Karmaşık örnekle kafam karıştı. Lütfen nasıl taklit edileceğini gösterebilir misiniz diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)?
— Martin Vegter

3

Birisi lütfen aşağıdaki örneğin nasıl uygulanacağını açıklayabilir mi?
diff <(cat "$2" | xz -d) <(cat "$1" | xz -d)

Ben adlandırılmış borular yönlendirme daha grok için daha basit olduğunu düşünüyorum, yani en basit terimlerle:

mkfifo p1 p2               # create pipes
cat "$2" | xz -d > p1 &    # start the commands in the background
cat "$1" | xz -d > p2 &    #    with output to the pipes
diff p1 p2                 # run 'diff', reading from the pipes
rm p1 p2                   # remove them at the end

p1ve p2geçici olarak adlandırılan borularsa, herhangi bir şey olarak adlandırılabilir.

Boruları /tmp, örneğin Gilles'in cevabının gösterdiği bir dizinde oluşturmak ve catburada ihtiyacınız olmadığını unutmayın , bu yüzden:

tmpdir=$(mktemp -d)
mkfifo "$tmpdir/p1" "$tmpdir/p2"
xz -d < "$2" > "$tmpdir/p1" &
xz -d < "$1" > "$tmpdir/p2" &
diff "$tmpdir/p1" "$tmpdir/p2"
rm -r "$tmpdir"

(Büyük olasılıkla tırnak işaretleri olmadan da kaçabilirsiniz, çünkü mktempbüyük olasılıkla "güzel" dosya adları oluşturur.)

Boru çözümü, ana komut ( diff) tüm girdiyi okumadan önce ölürse, arka plan işlemlerinin asılı bırakılabileceği uyarısına sahiptir .


0

Ne dersin:

cat "$2" | xz -d | diff /dev/sdtin /dev/stderr 2<<EOT
`cat "$1" | xz -d`
EOT
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.