จัดรูปแบบไฟล์ XML จำนวนมาก


11

ฉันจัดการไฟล์ XML จำนวนมากที่กระจัดกระจายไปทั่วโครงสร้างไดเรกทอรีที่ซ้อนกัน

ฉันพยายามต่อไปนี้:

$ find . -name "*.xml" -type f | xargs -- xmllint --format

ปัญหาคือการสร้างผลลัพธ์ XML ที่จัดรูปแบบแล้วบนหน้าจอ แต่จะไม่เปลี่ยนไฟล์

ฉันจะเปลี่ยนคำสั่งนี้เพื่อให้เนื้อหาไฟล์จริงมีการเปลี่ยนแปลงได้อย่างไร?

คำตอบ:


23

สามารถทำได้จากการfindใช้โดยตรง-exec:

find . -name "*.xml" -type f -exec xmllint --output '{}' --format '{}' \;

สิ่งที่ถูกส่งไปยัง-execจะถูกเรียกใช้หนึ่งครั้งต่อไฟล์ที่พบโดยพารามิเตอร์เทมเพลต{}จะถูกแทนที่ด้วยชื่อไฟล์ปัจจุบัน \;ในตอนท้ายของการค้นหาคำสั่งเพียงแค่สิ้นสุดบรรทัด

การใช้xargsไม่จำเป็นจริงๆในกรณีนี้เพราะเราจำเป็นต้องเรียกใช้xmllintหนึ่งครั้งต่อไฟล์เนื่องจากต้องระบุทั้งชื่ออินพุตและไฟล์เอาต์พุตในการโทรเดียวกัน

xargsจะต้องใช้ถ้าคำสั่งที่ถูกไพพ์ไปยังจาก find กำลังทำงานกับหลายไฟล์พร้อมกันและรายการนั้นยาว คุณไม่สามารถทำเช่นนั้นในกรณีนี้ตามที่คุณต้องการที่จะผ่านชื่อไฟล์เดียวกับตัวเลือกของ--output xmllintหากไม่มีxargsข้อผิดพลาด "รายการอาร์กิวเมนต์ยาวเกินไป" หากคุณกำลังประมวลผลไฟล์จำนวนมาก xargsยังรองรับไฟล์แทนที่สตริงด้วย-Iตัวเลือก:

find . -name "*.xml" -type f | xargs -I'{}' xmllint --output '{}' --format '{}'

จะทำเช่นเดียวกันกับfind -execคำสั่งด้านบน ถ้าใด ๆ ของโฟลเดอร์ของคุณมีตัวอักษรแปลกในพื้นที่เช่นคุณจะต้องใช้-0ตัวเลือกของและfind xargsแต่การใช้xargsที่มี-Iนัยตัวเลือก-L 1ซึ่งหมายถึงเฉพาะการประมวลผล 1 ไฟล์ในเวลาอยู่แล้วดังนั้นคุณอาจรวมทั้งโดยตรงใช้กับfind-exec


@ การจัดการงานขอบคุณสำหรับการแก้ไข - นิ้วมือเหนียว; o)
didster

ฉันเพิ่งวิ่งและดูเหมือนว่าจะทำงานรักษา! ขอบคุณมากสำหรับคำตอบที่รวดเร็วและรัดกุม!
Harry

2
“ สิ่งนี้จะล้มเหลวหากรายการไฟล์ใหญ่เกินไป”: ไม่มันจะไม่ล้มเหลว (กำลังประมวลผลไฟล์ครั้งละหนึ่งไฟล์) และอันที่จริงแล้วfind … -execเป็นวิธีที่ตรงที่สุดในการทำเช่นนี้
Gilles 'SO- หยุดความชั่วร้าย'

@Gilles จุดดี! ฉันได้ปรับปรุงคำตอบของฉันแล้ว
didster

1
ทำงานได้เนื่องจากความจริงที่ว่าxmllintตอนแรกโหลดเอกสาร xml แบบเต็มลงในหน่วยความจำแล้วจึงแยก / เขียนออกเท่านั้น อนุญาตให้มีการประมวลผลเอกสารในสถานที่
gavenkoa

6

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

#! /bin/sh
for file
do
   xmllint --format $file > $file.tmp && mv $file.tmp $file
done

ลองใช้กับไฟล์หนึ่งหรือสองไฟล์ด้วยมือจากนั้นคุณสามารถแทนที่มันใน xargs

find . -name "*.xml" -type f | xargs -- xmltidy.sh

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