ไฟล์หลอกสำหรับข้อมูลชั่วคราว


98

ฉันมักจะต้องการดึงข้อมูลสตริงที่ค่อนข้างสั้น (อาจมีหลายบรรทัด) ไปยังโปรแกรม commandline ซึ่งยอมรับเฉพาะอินพุตจากไฟล์ (เช่น wdiff) ในรูปแบบซ้ำ ๆ แน่ใจว่าฉันสามารถสร้างไฟล์ชั่วคราวอย่างน้อยหนึ่งไฟล์บันทึกสตริงที่นั่นและรันคำสั่งด้วยชื่อไฟล์เป็นพารามิเตอร์ แต่ดูเหมือนว่าฉันว่าขั้นตอนนี้จะไม่มีประสิทธิภาพสูงถ้าข้อมูลถูกเขียนลงดิสก์จริงและอาจเป็นอันตรายต่อดิสก์ได้มากกว่าที่จำเป็นถ้าฉันทำซ้ำขั้นตอนนี้หลายครั้งเช่นถ้าฉันต้องการป้อนข้อความบรรทัดเดียวแบบยาว ไฟล์เพื่อ wdiff มีวิธีแนะนำให้หลีกเลี่ยงสิ่งนี้โดยใช้ไฟล์หลอกเช่นไพพ์เพื่อเก็บข้อมูลชั่วคราวโดยไม่ต้องเขียนลงดิสก์ (หรือเขียนเฉพาะในกรณีที่เกินความยาววิกฤติ) โปรดทราบว่า wdiff รับสองอาร์กิวเมนต์และwdiff <"text".


สามารถแก้ไขได้ผ่านทางนี้xargsหรือไม่
NN

ไม่ทราบ แต่จะไม่ชัดเจนสำหรับฉันอย่างไร เท่าที่ฉันเข้าใจxargsจะทำให้บรรทัดอินพุตจากอาร์กิวเมนต์สตริงไฟล์สำหรับคำสั่ง แต่ฉันต้องการสิ่งที่ตรงกันข้าม
highsciguy

@rahmu ฉันได้ดู แต่ฉันคิดว่าการตั้งค่าปัญหาแตกต่างกันเล็กน้อย อย่างน้อยฉันก็ไม่เห็นว่าคำตอบจะช่วยได้อย่างไร คำตอบที่ได้รับการยอมรับในการผลิตไฟล์ชั่วคราวอย่างถูกต้องเป็นสิ่งที่ฉันไม่ควรหลีกเลี่ยงหากไม่มีบัฟเฟอร์บางชนิดซึ่งป้องกันการเขียนไฟล์จริงๆ ฉันมีความเข้าใจที่ จำกัด ว่าไฟล์ temp ทำงานอย่างไร!
highsciguy

มีอะไรผิดปกติกับecho $data_are_here | dumb_program?
vonbrand

1
สิ่งนี้จะสนับสนุนอินพุตไฟล์เดียวเท่านั้นและไม่ใช่ทุกโปรแกรมที่จะอ่านจาก stdin
highsciguy

คำตอบ:


55

ใช้ไปป์ที่มีชื่อ ตามภาพประกอบ:

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

การ-eบอกให้สะท้อนอย่างถูกต้องตีความ newline escape ( \n) สิ่งนี้จะบล็อกนั่นคือเปลือกของคุณจะแขวนจนกว่าจะมีบางอย่างอ่านข้อมูลจากไปป์

เปิดเชลล์อื่นที่ใดที่หนึ่งและในไดเรกทอรีเดียวกัน:

cat fifo

คุณจะอ่านเสียงก้องซึ่งจะปล่อยเปลือกอื่น ๆ แม้ว่าไพพ์จะมีอยู่เป็นไฟล์โหนดบนดิสก์ข้อมูลที่ผ่านก็ไม่ได้ ทุกอย่างเกิดขึ้นในหน่วยความจำ คุณสามารถพื้นหลัง ( &) เสียงสะท้อน

ไพพ์มีบัฟเฟอร์ 64k (บน linux) และเช่นเดียวกับซ็อกเก็ตจะบล็อกตัวเขียนเมื่อเต็มดังนั้นคุณจะไม่สูญเสียข้อมูลตราบใดที่คุณไม่ได้ฆ่านักเขียนก่อนกำหนด


โอเคขอบคุณมันใช้งานได้กับสองชื่อ pipes และ wdiff แต่ฉันคิดว่าจะเข้าใจว่ามีหน่วยความจำ (เล็ก) จำนวนหนึ่งสำหรับไพพ์เป็นบัฟเฟอร์ จะเกิดอะไรขึ้นถ้าฉันเกินขนาดบัฟเฟอร์
highsciguy

ฉันเพิ่มย่อหน้าสุดท้ายเกี่ยวกับปัญหานั้น
goldilocks

3
/tmpถูกกำหนดค่าใน distros ส่วนใหญ่เพื่อใช้tmpfsระบบไฟล์ที่อยู่ใน RAM เมื่อคุณเขียนไฟล์/tmpมันจะตรงไปยัง RAM ของคุณซึ่งทำให้เป็นคำตอบที่ดีสำหรับไฟล์กึ่งยืดหยุ่นที่ต้องเข้าถึงได้อย่างรวดเร็วและเขียนใหม่หลายครั้ง

129

ใน Bash คุณสามารถใช้command1 <( command0 )ไวยากรณ์การเปลี่ยนเส้นทางซึ่งเปลี่ยนเส้นทางcommand0ของ stdout และส่งผ่านไปยังcommand1ชื่อไฟล์ที่ใช้เป็นอาร์กิวเมนต์บรรทัดคำสั่ง นี้เรียกว่าขั้นตอนการเปลี่ยนตัว

บางโปรแกรมที่รับอาร์กิวเมนต์บรรทัดคำสั่งของชื่อไฟล์จำเป็นต้องมีไฟล์การเข้าถึงแบบสุ่มจริงดังนั้นเทคนิคนี้จะไม่ทำงานสำหรับโปรแกรมเหล่านั้น อย่างไรก็ตามมันใช้งานได้ดีกับwdiff:

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

ในพื้นหลังสิ่งนี้จะสร้าง FIFO ไพพ์คำสั่งภายใน<( )ไปยัง FIFO และส่งไฟล์ descriptor ของ FIFO เป็นอาร์กิวเมนต์ หากต้องการดูว่าเกิดอะไรขึ้นลองใช้มันechoเพื่อพิมพ์อาร์กิวเมนต์โดยไม่ทำอะไรเลย:

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

การสร้างไปป์ที่มีชื่อนั้นมีความยืดหยุ่นมากกว่า (ถ้าคุณต้องการเขียนตรรกะการเปลี่ยนเส้นทางที่ซับซ้อนโดยใช้กระบวนการหลายอย่าง) แต่สำหรับวัตถุประสงค์หลายอย่างเพียงพอแล้วและเห็นได้ชัดว่าใช้ง่ายกว่า

นอกจากนี้ยังมี>( )ไวยากรณ์สำหรับเมื่อคุณต้องการที่จะใช้มันเป็นเอาท์พุทเช่น

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

ดูเพิ่มเติมที่สูตรโกงการเปลี่ยนเส้นทาง Bashสำหรับเทคนิคที่เกี่ยวข้อง


สิ่งนี้ไม่ได้รับการสนับสนุนใน KSH
chanchal1987

5
ksh คิดค้นสิ่งนี้ คุณกำลังใช้ตัวแปร ksh ที่ไม่รองรับมัน
Neil McGuigan

2
บางโปรแกรมที่รับอาร์กิวเมนต์บรรทัดคำสั่งของชื่อไฟล์จำเป็นต้องมีไฟล์การเข้าถึงแบบสุ่มจริงดังนั้นเทคนิคนี้จะไม่ทำงานสำหรับโปรแกรมเหล่านั้น คุณทำอะไรในกรณีเหล่านี้ ตัวอย่างเช่นssh -F <(vagrant ssh-config) defaultจะดีจริงๆ แต่อนิจจา
Sukima

10

wdiff เป็นกรณีพิเศษเนื่องจากต้องการ 2 อาร์กิวเมนต์ชื่อไฟล์ แต่สำหรับคำสั่งทั้งหมดที่ต้องการเพียง 1 อาร์กิวเมนต์เท่านั้นและที่ดื้อรั้นปฏิเสธที่จะทำอะไรนอกจากอาร์กิวเมนต์ชื่อไฟล์มี 2 ตัวเลือก:

  • ชื่อไฟล์ '-' (นั่นคือเครื่องหมายลบ) ทำงานประมาณ 1/2 ของเวลา ดูเหมือนว่าจะขึ้นอยู่กับคำสั่งที่มีปัญหาและไม่ว่าจะเป็นนักพัฒนาของคำสั่งกับดักกรณีที่และจัดการกับมันตามที่คาดไว้ เช่น

    $> ls | แมว -

  • มีไฟล์ psuedo ชื่อ / dev / stdin ที่มีอยู่ใน linux และสามารถใช้งานได้เป็นชื่อไฟล์ที่จำเป็นอย่างยิ่งโดยคำสั่ง สิ่งนี้มีแนวโน้มที่จะใช้งานได้เนื่องจากไม่ต้องการการจัดการชื่อไฟล์พิเศษจากคำสั่ง หาก Fifo ทำงานหรือวิธีการแทนที่กระบวนการทุบตีทำงานดังนั้นสิ่งนี้ก็ควรใช้งานได้และไม่ใช่เชลล์เฉพาะ เช่น

    $> ls | cat / dev / stdin


1
น้อยลงและ openssl เช่น / dev / stdin มากกว่า / dev / fd / NUM :-)
eel ghEEz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.