Geçici veri için sahte dosyalar


98

Sıklıkla, yalnızca dosyalardan (örneğin wdiff) girdi girişini tekrar eden bir şekilde kabul eden programları komut satırına nispeten kısa dize verileri (ancak birkaç satır olabilir) beslemek istiyorum. Tabii ki bir veya daha fazla geçici dosya oluşturabilirim, dizgiyi oraya kaydedebilir ve komutu dosya adı ile parametre olarak çalıştırabilirim. Ancak, eğer veri diske gerçekten yazılırsa, bu prosedür çok verimsiz geliyormuş gibi görünüyor ve ayrıca bu işlemi birçok kez tekrarlarsam, örneğin uzun metin satırlarını tek tek beslemek istersem diske gerekenden daha fazla zarar verebilir gibi görünüyor. wdiff için dosyalar. Bunu atlatmanın önerilen bir yolu var mı, yani verileri diske yazmadan (veya yalnızca kritik bir uzunluğu aşarsa yazarak) geçici olarak saklamak için borular gibi sahte dosyaları kullanarak. Wdiff’in iki argüman aldığını vewdiff <"text".


Bu çözülebilir xargsmi?
NN

Bilmiyorum, ama bana nasıl yapılacağı belli olmaz. Anladığım kadarıyla xargsgirdi satırlarını komut dizgesindeki dosya dizgisi argümanlarından yapar. Ama tam tersine ihtiyacım var.
highsciguy

@rahmu Bir göz attım, ancak sorun ayarının orada biraz farklı olduğunu düşünüyorum. En azından cevapların nasıl yardımcı olacağını anlamıyorum. Geçici dosyaları düzgün bir şekilde üretmek için kabul edilen cevap, aslında dosyaları yazmayı engelleyen bir tür tamponlama yoksa, kaçınmak istemeyeceğim şeydir. Temp dosyalarının nasıl çalıştığını anladım!
Highsciguy

Neyin var echo $data_are_here | dumb_program?
von

1
Bu sadece bir giriş dosyasını destekleyecektir ve tüm programlar stdin'den okumaz.
highsciguy

Yanıtlar:


55

Adlandırılmış bir boru kullanın . Illüstrasyon yoluyla:

mkfifo fifo
echo -e "hello world\nnext line\nline 3" > fifo

-eDüzgün satır kaçış yorumlamak için yankı söyler ( \n). Bu bloke olur, yani bir şey borudan veri okuyana kadar kabuğunuz kilitlenir.

Bir yerde ve aynı dizinde başka bir kabuk aç:

cat fifo

Diğer kabuğu serbest bırakacak olan ekoyu okuyacaksınız. Her ne kadar boru diskte bir dosya düğümü olarak mevcut olsa da, içinden geçen veriler olmaz; her şey bellekte yer alır. &Ekoyu arka planda ( ) yapabilirsiniz .

Borunun 64k tamponu (linux üzerinde) vardır ve bir soket gibi, doluysa yazarı engeller, bu yüzden yazarı erken öldürmediğiniz sürece veri kaybetmezsiniz.


Tamam, teşekkürler, bu iki adlandırılmış yöneltme ve boru ile de çalışır. Ancak, boru için tampon olarak belirli (küçük) miktarda bellek olduğunu anladığımı düşündüm. Tampon boyutunu aşarsam ne olur?
Highsciguy

Bu konuda son bir paragraf ekledim.
goldilocks

3
/tmpçoğu dağıtımda tmpfsRAM'de bulunan bir dosya sistemi kullanacak şekilde yapılandırılır . Bir dosyayı /tmpyazdığınızda, doğrudan RAM'inize gider, bu da hızlı bir şekilde erişilmesi ve birçok kez yeniden yazılması gereken yarı esnek dosyalar için iyi bir cevaptır.

129

Bash'de, stdout'unu command1 <( command0 )yönlendiren command0ve onu command1bir dosya adı komut satırı argümanı olarak alan bir öğeye ileten yeniden yönlendirme sözdizimini kullanabilirsiniz . Buna işlem ikamesi denir .

Dosya adı komut satırı argümanlarını alan bazı programlar gerçekte gerçek bir rasgele erişim dosyasına ihtiyaç duyar, bu nedenle bu teknik olanlar için çalışmaz. Ancak, iyi çalışıyor wdiff:

user@host:/path$ wdiff <( echo hello; echo hello1 ) <( echo hello; echo hello2 )
hello
[-hello1-]
{+hello2+}

Arka planda, bu bir FIFO oluşturur, komutun içine <( )FIFO'yu iletir ve FIFO'nun dosya tanımlayıcısını argüman olarak iletir. Neler olduğunu görmek için, onunla echohiçbir şey yapmadan argümanı yazdırmak için kullanmayı deneyin :

user@host:/path$ echo <( echo hello )
/dev/fd/63

Adlandırılmış bir boru oluşturmak daha esnektir (birden fazla işlem kullanarak karmaşık yönlendirme mantığı yazmak istiyorsanız), ancak birçok amaç için bu yeterlidir ve kullanımı açıkça kolaydır.

>( )Çıktı olarak kullanmak istediğinizde, örneğin sözdizimi de var.

$ someprogram --logfile >( gzip > out.log.gz )

Ayrıca ilgili teknikler için Bash yönlendirmeleri hile sayfasına bakınız .


Bu
KSH'de

5
ksh bunu icat etti. Onu desteklemeyen bir ksh çeşidi kullanıyorsunuz
Neil McGuigan

2
Dosya adı komut satırı argümanlarını alan bazı programlar gerçekte gerçek bir rasgele erişim dosyasına ihtiyaç duyar, bu nedenle bu teknik olanlar için çalışmaz. Bu durumlarda ne yaparsın? Mesela ssh -F <(vagrant ssh-config) defaultne yazık ki gerçekten güzel olurdu.
Sukima

10

wdiff, 2 dosya adı argümanı gerektiren özel bir durumdur, ancak sadece 1 argüman gerektiren ve inatla bir dosya adı argümanı dışında bir şey almayı reddeden tüm komutlar için 2 seçenek vardır:

  • Dosya adı '-' (yani, eksi işareti), zamanın yaklaşık 1 / 2'sini oluşturur. Söz konusu komuta ve komuta sahip geliştiricinin bu olayı yakalayıp yakalamadığı gibi ele alınıp alınmadığına bağlı görünüyor. Örneğin

    $> ls | kedi -

  • / Dev / stdin adında linux'da bulunan ve kullanılabilecek bir psuedo dosyası var. Bu, komut için herhangi bir özel dosya adı işlemesi gerektirmediğinden işe yarar. Bir fifo çalışırsa veya bash işlem ikame metodu işe yararsa, o zaman bu da işe yaramalı ve kabuğa özgü olmamalıdır. Örneğin

    $> ls | kedi / dev / stdin


1
daha az ve openssl gibi / dev / fd / NUM yerine / dev / stdin :-)
eel ghEEz
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.