การเรียงลำดับรองรับการเรียงลำดับไฟล์ในสถานที่เช่น `sed --in-place` หรือไม่?


80

ฉันตาบอดหรือมีตัวเลือกที่ไม่เหมือนใคร--in-placeสำหรับsort?

เพื่อบันทึกผลลัพธ์ไปยังไฟล์อินพุต sed use -i( --in-place)

การเปลี่ยนทิศทางเอาต์พุตของsortไปยังไฟล์อินพุต

sort < f > f

ผลลัพธ์ในการทำให้ว่างเปล่า หากไม่มี--in-placeตัวเลือก - อาจมีเคล็ดลับวิธีการทำสิ่งนี้ด้วยวิธีที่สะดวก

(สิ่งเดียวที่มาในใจของฉัน:

sort < f > /tmp/f$$ ; cat /tmp/f$$ > f ; rm /tmp/f$$

การย้ายไม่ใช่ตัวเลือกที่ถูกต้องอาจทำให้สิทธิ์ในการใช้ไฟล์เปลี่ยนไป นั่นเป็นเหตุผลที่ฉันเขียนทับเนื้อหาของไฟล์ temp ที่ฉันลบออกไป)


นอกจากนี้ยังinsituอนุญาตให้ใช้คำสั่งใด ๆ ในสถานที่
sr_

@sr_ นั่นเป็นคำสั่งที่น่าสนใจ แต่มันไม่ทำงานกับคำสั่งใด ๆ มีเพียงคำสั่งที่เขียนไม่เร็วกว่าที่อ่าน (มิฉะนั้นมันจะอุดตันไฟล์อินพุตก่อนที่คำสั่งจะอ่าน) ไม่มีการรับประกันว่าจะใช้งานsortได้
cjm

@cjm, ฉันจริงๆไม่แน่ใจ แต่ไม่ได้นี้ควรจะจัดการกับกรณีที่?
sr_

@sr_ ฉันคิดว่าคุณพูดถูก ฉันอ่านคำอธิบายแทนที่จะมองไปที่ต้นฉบับ แม้ว่าไฟล์ขนาดใหญ่จริง ๆ มันอาจมีหน่วยความจำไม่เพียงพอสำหรับบัฟเฟอร์และข้อขัดข้อง (ดูเหมือนจะตรวจสอบว่า NULL return จาก malloc)
cjm

@cjm: โอ้ใช่แน่นอน
sr_

คำตอบ:


110

sortมี-o, --outputตัวเลือกที่ใช้ชื่อไฟล์เป็นอาร์กิวเมนต์ ถ้ามันเหมือนกับไฟล์อินพุตมันจะเขียนผลลัพธ์ไปยังไฟล์ชั่วคราวจากนั้นเขียนทับไฟล์อินพุตดั้งเดิม (เหมือนกับสิ่งที่sed -iทำ)

จากGNU sortหน้าข้อมูล:

`-o OUTPUT-FILE'
`--output=OUTPUT-FILE'
      Write output to OUTPUT-FILE instead of standard output.  Normally,
      `sort' reads all input before opening OUTPUT-FILE, so you can
      safely sort a file in place by using commands like `sort -o F F'
      and `cat F | sort -o F'.  However, `sort' with `--merge' (`-m')
      can open the output file before reading all input, so a command
      like `cat F | sort -m -o F - G' is not safe as `sort' might start
      writing `F' before `cat' is done reading it.

      On newer systems, `-o' cannot appear after an input file if
      `POSIXLY_CORRECT' is set, e.g., `sort F -o F'.  Portable scripts
      should specify `-o OUTPUT-FILE' before any input files.

และจากข้อกำหนดคุณสมบัติพื้นฐานของ Open Group ฉบับที่ 7 :

-o  output
    Specify the name of an output file to be used instead of the standard 
    output. This file can be the same as one of the input files.

แน่นอน! มันได้ผล ! ฉันไม่เห็นร่องรอยใด ๆ เกี่ยวกับเรื่องนี้man sort- เป็นคุณลักษณะที่ไม่มีเอกสารหรือไม่ มันเป็นมาตรฐานและพกพา?
Grzegorz Wierzowiecki

@GrzegorzWierzowiecki: ดูการอัปเดต
enzotib

คำตอบที่ดี :)
Grzegorz Wierzowiecki

1
โดยสรุป: sort -o <filename> <filename>จะจัดเรียงไฟล์อย่างปลอดภัย
phyatt

11

คุณสามารถใช้spongeฟังก์ชั่นที่ดูดซับstdinแล้วเขียนไปยังไฟล์เช่น:

sort < f | sponge f

ข้อเสียของspongeมันคือมันจะเก็บเอาท์พุทชั่วคราวในหน่วยความจำซึ่งอาจเป็นปัญหาสำหรับไฟล์ขนาดใหญ่ มิฉะนั้นคุณต้องเขียนมันลงในไฟล์ก่อนแล้วจึงเขียนทับไฟล์ต้นฉบับ

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


7

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

มีโปรแกรมไม่กี่โปรแกรม (ส่วนใหญ่เป็น GNU) มีตัวเลือกแบบแทนที่ (เช่น-iใน perl และ GNU sed; -oใน GNU sort) พวกเขาทำงานโดยการใส่ข้อมูลในไฟล์ชั่วคราวแล้วย้ายเข้าที่ สำหรับโปรแกรมที่ไม่มีตัวเลือกดังกล่าวโคลินวัตสันspongeยูทิลิตี้ (รวมอยู่ในmoreutils โจอี้ของเดิม ) จะทำงานได้อย่างปลอดภัยสำหรับโปรแกรมใด ๆ (ตัวอย่าง: ฉันสามารถทำให้cut? เปลี่ยนไฟล์ในสถานที่ ; ฉันจะทำให้ iconv แทนที่แฟ้มใส่กับแปลง เอาท์พุท? )

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

cp -p f ~/f.backup
sort <~/f.backup >|f
rm ~/f.backup # optional

1
sort -oไม่ได้เป็นของ GNU โดยเฉพาะและได้รับการออกแบบมาเป็นพิเศษเพื่อแทนที่ไฟล์นั้น sortไม่สามารถเริ่มเขียนเอาต์พุตก่อนที่จะอ่านอินพุตเต็มที่ (ใช้หน่วยความจำหรือไฟล์ชั่วคราวเพื่อเก็บข้อมูล) ดังนั้นจึงค่อนข้างเป็นธรรมชาติว่ามันควรจะสามารถแทนที่อินพุตของมันได้
Stéphane Chazelas

และที่จริงมันเป็นกรณีหนึ่งที่ GNU sortไม่ใช่ POSIX เนื่องจากsort -mo file1 file1 file2ไม่รับประกันว่าจะทำงานได้ในขณะที่คนดั้งเดิมsortรู้วิธีการแก้ไขนั้น (อ่านใน Unix V7 ในยุค 70)
Stéphane Chazelas

@JoelCross Odd sort -oทำงานกับฉันด้วย coreutils 8.25 และมีการบันทึกคุณสมบัติไว้ในคู่มือ (สังเกตว่ามันเป็นเพียงกรณีการเรียงลำดับไม่ใช่เมื่อรวมเข้าด้วยกัน) หากคุณสามารถทำซ้ำสิ่งนี้ได้ให้ส่งรายงานข้อผิดพลาด (ระบุบรรทัดคำสั่งที่แน่นอนไฟล์อินพุตที่แน่นอนระบบที่คุณใช้งานอยู่และวิธีที่คุณได้รับไบนารี)
Gilles

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