คำเตือนเกี่ยวกับ '>'
ผู้เริ่มต้น Unix ที่เพิ่งเรียนรู้เกี่ยวกับการเปลี่ยนเส้นทาง I / O ( <
และ>
) มักจะลองทำสิ่งต่าง ๆ เช่น
คำสั่ง … input_file > the_same_file
หรือ
คำสั่ง … < ไฟล์ > the_same_file
หรือเกือบเท่ากัน
แมวไฟล์ | คำสั่ง …> the_same_file
( grep
, sed
, cut
, sort
และspell
เป็นตัวอย่างของคำสั่งที่ผู้คนกำลังล่อลวงเพื่อใช้ในการสร้างเช่นนี้.) ผู้ใช้จะประหลาดใจที่พบว่าสถานการณ์เหล่านี้ส่งผลให้ในไฟล์กลายเป็นที่ว่างเปล่า
ความแตกต่างที่ดูเหมือนจะไม่ได้กล่าวถึงในคำตอบอื่น ๆ สามารถพบได้ในประโยคแรกของส่วนการเปลี่ยนเส้นทางของbash (1) :
ก่อนที่จะดำเนินการคำสั่งอินพุตและเอาต์พุตอาจถูกเปลี่ยนทิศทาง
โดยใช้สัญลักษณ์พิเศษที่ตีความโดยเชลล์
ห้าคำแรกควรจะเป็นตัวหนาตัวเอียงขีดเส้นใต้ขยายกระพริบสีแดงและมีเครื่องหมายไอคอนเพื่อเน้นความจริงที่ว่าเปลือกดำเนินการเปลี่ยนเส้นทางการร้องขอ (s)
ก่อนที่คำสั่งจะถูกดำเนินการ และจำไว้ด้วย
การเปลี่ยนเส้นทางของผลลัพธ์ทำให้ไฟล์…ถูกเปิดเพื่อเขียน…. หากไฟล์ไม่มีอยู่ไฟล์จะถูกสร้างขึ้น ถ้ามันมีอยู่มันจะถูกตัดให้มีขนาดเป็นศูนย์
ดังนั้นในตัวอย่างนี้:
sort roster > roster
เชลล์จะเปิดroster
ไฟล์เพื่อเขียนตัดทอน (เช่นการละทิ้งเนื้อหาทั้งหมด) ก่อนที่sort
โปรแกรมจะเริ่มทำงาน โดยธรรมชาติแล้วไม่มีสิ่งใดที่สามารถกู้คืนข้อมูลได้
บางคนอาจคาดหวังอย่างนั้นไม่ได้
tr "[:upper:]" "[:lower:]" < poem > poem
อาจจะดีกว่า เนื่องจากเชลล์จัดการการเปลี่ยนเส้นทางจากซ้ายไปขวาจึงเปิดpoem
สำหรับการอ่าน (สำหรับtr
อินพุตมาตรฐาน) ก่อนที่จะเปิดเพื่อเขียน (สำหรับเอาต์พุตมาตรฐาน) แต่มันก็ไม่ได้ช่วยอะไร แม้ว่าการดำเนินการตามลำดับนี้จะให้ทั้งสองไฟล์จัดการ แต่ทั้งคู่ก็ชี้ไปที่ไฟล์เดียวกัน เมื่อเชลล์เปิดไฟล์เพื่ออ่านเนื้อหาจะยังคงอยู่ที่นั่น แต่ก็ยังคงถูกบล็อกก่อนที่โปรแกรมจะทำงาน
ดังนั้นจะทำอย่างไรกับมัน?
โซลูชั่นรวมถึง:
ตรวจสอบว่าโปรแกรมที่คุณกำลังเรียกใช้มีความสามารถของตัวเองภายในความสามารถในการระบุตำแหน่งที่จะออก ซึ่งมักจะถูกระบุด้วยโทเค็น-o
(หรือ--output=
) โดยเฉพาะอย่างยิ่ง,
sort roster -o roster
เทียบเท่ากับ
sort roster > roster
ยกเว้นในกรณีแรกsort
โปรแกรมจะเปิดไฟล์เอาต์พุต และมันก็ฉลาดพอที่จะไม่เปิดไฟล์ที่ส่งออกจนกระทั่งหลังจากที่มันได้อ่านทั้งหมดของแฟ้มใส่ (s)
ในทำนองเดียวกันอย่างน้อยบางรุ่นsed
มี-i
(แก้ไขฉัน n วาง) ตัวเลือกที่สามารถนำมาใช้ในการเขียนการส่งออกกลับออกไปยังแฟ้มใส่ (อีกครั้งหลังจากที่ป้อนข้อมูลทั้งหมดที่ได้รับการอ่าน) บรรณาธิการเช่นed
/ ex
, emacs
, pico
และvi
/ vim
อนุญาตให้ผู้ใช้แก้ไขไฟล์ข้อความและบันทึกข้อความที่แก้ไขในไฟล์ต้นฉบับ โปรดทราบว่าed
(อย่างน้อย) สามารถใช้แบบไม่โต้ตอบ
vi
มีคุณสมบัติที่เกี่ยวข้อง หากคุณพิมพ์มันจะเขียนเนื้อหาของบัฟเฟอร์การแก้ไขออกไปอ่านเอาต์พุตและแทรกลงในบัฟเฟอร์ (แทนที่เนื้อหาต้นฉบับ):%!command
Entercommand
เรียบง่าย แต่มีประสิทธิภาพ:
คำสั่ง … input_file > temp_file && mv temp_file input_file
นี่คือข้อเสียเปรียบที่ถ้าinput_file
เป็นลิงค์มันจะ (อาจ) ถูกแทนที่ด้วยไฟล์แยกต่างหาก นอกจากนี้ไฟล์ใหม่จะเป็นของคุณโดยมีการป้องกันเริ่มต้น โดยเฉพาะอย่างยิ่งสิ่งนี้มีความเสี่ยงที่ไฟล์จะจบลงด้วยการอ่านได้ทั่วโลกแม้ว่าจะไม่ใช่ไฟล์ต้นฉบับinput_file
ก็ตาม
รูปแบบ:
command … input_file > temp_file && cp temp_file input_file && rm temp_file
ซึ่งจะยังคง (อาจ) ปล่อยให้temp_file
โลกสามารถอ่านได้ ดียิ่งขึ้น:
cp input_file temp_file && command … temp_file > input_file && rm temp_file
สิ่งเหล่านี้จะรักษาสถานะลิงก์เจ้าของและโหมด (การป้องกัน) ของไฟล์ซึ่งอาจมีค่าใช้จ่าย I / O มากเป็นสองเท่า (คุณอาจต้องใช้ตัวเลือกเช่น-a
หรือ-p
เปิดcp
เพื่อบอกให้รักษาแอตทริบิวต์)
command … input_file > temp_file &&
cp --attributes-only --preserve=all input_file temp_file &&
mv temp_file input_file
(แยกออกเป็นบรรทัดแยกกันเพื่อให้สามารถอ่านได้เท่านั้น) วิธีนี้จะรักษาโหมดของไฟล์ไว้ (และหากคุณเป็นเจ้าของ, เจ้าของ) แต่ทำให้มันเป็นของคุณ (ถ้าคุณไม่ได้รูท) และทำให้มันใหม่ แยกไฟล์
บล็อกนี้
(แก้ไข "ไฟล์") แนะนำและอธิบาย
{rm input_file && คำสั่ง …> input_file ; } < input_file
สิ่งนี้ต้องการcommand
ให้สามารถประมวลผลอินพุตมาตรฐาน (แต่ตัวกรองเกือบทั้งหมดสามารถทำได้) บล็อกตัวเองเรียกสิ่งนี้ว่ากระบองที่มีความเสี่ยงและไม่สนับสนุนการใช้งาน และสิ่งนี้จะสร้างไฟล์ใหม่แยกต่างหาก (ไม่เชื่อมโยงกับอะไรเลย) ซึ่งคุณเป็นเจ้าของและมีสิทธิ์เริ่มต้น
แพ็คเกจ moreutils มีคำสั่งที่เรียกว่าsponge
:
คำสั่ง … input_file | ฟองน้ำthe_same_file
ดูคำตอบนี้สำหรับข้อมูลเพิ่มเติม
นี่คือสิ่งที่ทำให้ฉันประหลาดใจโดยสมบูรณ์:
syntaxerror พูดว่า :
[โซลูชันเหล่านี้ส่วนใหญ่] จะล้มเหลวในระบบไฟล์แบบอ่านอย่างเดียวโดยที่“ อ่านอย่างเดียว” หมายความว่าคุณ$HOME
จะเขียนได้ แต่/tmp
จะอ่านได้อย่างเดียว (โดยค่าเริ่มต้น) ตัวอย่างเช่นหากคุณมี Ubuntu และคุณได้บูทเข้าสู่ Recovery Console นี่เป็นกรณีปกติ นอกจากนี้ผู้ประกอบการเอกสารที่นี่<<<
จะไม่ทำงานที่นั่นเพราะมันจะต้อง/tmp
มีการอ่าน / เขียน
เพราะมันจะเขียนไฟล์ชั่วคราวลงไปที่นั่นเช่นกัน
(เทียบกับคำถามนี้รวมstrace
เอาท์พุท 'd)
กรณีต่อไปนี้อาจใช้งานได้:
แล้วคำถามคืออะไร
นี่เป็นหัวข้อยอดนิยมใน U&L; มันถูกแก้ไขในคำถามต่อไปนี้:
…และนั่นไม่ใช่การนับผู้ใช้ขั้นสูงหรือถามอูบุนตู ฉันได้รวมข้อมูลจำนวนมากจากคำตอบของคำถามข้างต้นไว้ในคำตอบนี้ แต่ไม่ใช่ทั้งหมด (เช่นสำหรับข้อมูลเพิ่มเติมอ่านคำถามข้างต้นและคำตอบของพวกเขา)
ป.ล. ฉันไม่มีส่วนเกี่ยวข้องกับบล็อกที่ฉันอ้างถึงด้านบน