File semu untuk data sementara

98

Saya sering ingin memasukkan data string yang relatif singkat (bisa beberapa baris) ke program commandline yang hanya menerima input dari file (misalnya wdiff) secara berulang. Tentu saya bisa membuat satu atau lebih file sementara, simpan string di sana dan jalankan perintah dengan nama file sebagai parameter. Tetapi bagi saya seolah-olah prosedur ini akan sangat tidak efisien jika data benar-benar ditulis ke disk dan juga dapat membahayakan disk lebih dari yang diperlukan jika saya mengulangi prosedur ini berkali-kali, misalnya jika saya ingin memberi makan satu baris teks panjang file ke wdiff. Apakah ada cara yang disarankan untuk menghindari hal ini, katakanlah dengan menggunakan file semu seperti pipa untuk menyimpan data sementara tanpa benar-benar menulisnya ke disk (atau menulisnya hanya jika melebihi panjang kritis). Perhatikan bahwa wdiff mengambil dua argumen dan,wdiff <"text".

kelas tinggi
sumber
Bisakah ini diselesaikan melalui xargs?
NN
Tidak tahu, tapi tidak akan jelas bagi saya caranya. Sejauh yang saya mengerti xargsakan membuat baris input dari argumen string file untuk perintah. Tapi aku butuh yang sebaliknya.
highsciguy
@rahmu aku sudah melihat, tapi aku pikir pengaturan masalahnya sedikit berbeda di sana. Setidaknya saya tidak melihat bagaimana jawaban akan membantu. Jawaban yang diterima untuk menghasilkan file-file sementara dengan benar pada dasarnya adalah apa yang tidak ingin saya hindari, jika tidak ada semacam buffering yang sebenarnya mencegah penulisan file-file tersebut. Saya memiliki pemahaman terbatas tentang cara kerja file temp!
kelas tinggi
Ada apa dengan ini echo $data_are_here | dumb_program?
vonbrand
1
Ini hanya mendukung satu file input dan tidak semua program dapat membaca dari stdin.
kelas tinggi

Jawaban:

55

Gunakan pipa bernama . Sebagai ilustrasi:

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

The -ememberitahu gema untuk benar menafsirkan baris escape ( \n). Ini akan memblokir, yaitu, shell Anda akan hang sampai sesuatu membaca data dari pipa.

Buka shell lain di suatu tempat dan di direktori yang sama:

cat fifo

Anda akan membaca gema, yang akan melepaskan shell lainnya. Meskipun pipa ada sebagai simpul file pada disk, data yang melewatinya tidak; itu semua terjadi di memori. Anda dapat latar belakang ( &) gema.

Pipa tersebut memiliki buffer 64k (di linux) dan, seperti soket, akan memblokir penulis ketika penuh, sehingga Anda tidak akan kehilangan data selama Anda tidak membunuh penulis secara prematur.

goldilocks
sumber
Ok, terima kasih, ini berfungsi juga dengan dua pipa bernama dan wdiff. Tetapi saya berpikir untuk memahami bahwa ada sejumlah (kecil) memori yang tersedia untuk pipa sebagai penyangga. Apa yang terjadi jika saya melebihi ukuran buffer?
highsciguy
Saya menambahkan paragraf terakhir tentang masalah itu.
goldilocks
3
/tmpdikonfigurasikan di sebagian besar distro untuk menggunakan tmpfssistem file yang ada dalam RAM. Ketika Anda menulis file di /tmpdalamnya langsung ke RAM Anda yang membuat adalah jawaban yang baik untuk file semi-resilien yang harus diakses dengan cepat dan ditulis ulang berkali-kali.
129

Di Bash, Anda dapat menggunakan command1 <( command0 )sintaks pengalihan, yang mengarahkan ulang command0stdout dan meneruskannya ke command1yang mengambil nama file sebagai argumen baris perintah. Ini disebut proses substitusi .

Beberapa program yang menggunakan argumen nama-baris perintah sebenarnya membutuhkan file akses acak nyata, sehingga teknik ini tidak akan bekerja untuk mereka. Namun, ini berfungsi baik dengan wdiff:

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

Di latar belakang, ini menciptakan FIFO, menyalurkan perintah di dalam <( )ke FIFO, dan meneruskan deskriptor file FIFO sebagai argumen. Untuk melihat apa yang terjadi, coba gunakan dengannya echountuk mencetak argumen tanpa melakukan apa pun dengannya:

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

Membuat pipa bernama lebih fleksibel (jika Anda ingin menulis logika redirection yang rumit menggunakan beberapa proses), tetapi untuk banyak tujuan ini cukup, dan jelas lebih mudah digunakan.

Ada juga >( )sintaks ketika Anda ingin menggunakannya sebagai output, misalnya

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

Lihat juga lembar curang pengalihan Bash untuk teknik terkait.

Siput mekanik
sumber
Ini tidak didukung di KSH
chanchal1987
5
ksh menciptakan ini. Anda menggunakan varian ksh yang tidak mendukungnya
Neil McGuigan
2
Beberapa program yang menggunakan argumen nama-baris perintah sebenarnya membutuhkan file akses acak nyata, sehingga teknik ini tidak akan bekerja untuk mereka. Apa yang Anda lakukan dalam kasus ini. Misalnya ssh -F <(vagrant ssh-config) defaultakan sangat bagus tapi sayang.
Sukima
10

wdiff adalah kasus khusus karena membutuhkan 2 argumen nama file, tetapi untuk semua perintah yang hanya membutuhkan 1 argumen dan yang dengan keras kepala menolak untuk mengambil apa pun selain argumen nama file, ada 2 opsi:

  • Nama file '-' (yaitu, tanda minus) berfungsi sekitar 1/2 waktu. Tampaknya bergantung pada perintah yang dipermasalahkan dan apakah pengembang perintah tersebut menjebak kasus itu dan menanganinya seperti yang diharapkan. misalnya

    $> ls | kucing -

  • Ada file psuedo bernama / dev / stdin yang ada di linux dan dapat digunakan jika nama file mutlak diperlukan oleh sebuah perintah. Ini lebih cenderung berhasil karena tidak memerlukan penanganan nama file khusus dari perintah. Jika fifo berfungsi, atau metode substitusi proses bash berfungsi, maka ini juga harus berfungsi dan tidak spesifik untuk shell. misalnya

    $> ls | cat / dev / stdin

dabuntu
sumber
1
kurang dan openssl seperti / dev / stdin daripada / dev / fd / NUM :-)
eel ghEEz