Định dạng lại một số lượng lớn các tệp XML


11

Tôi đang thao tác một số lượng lớn các tệp XML nằm rải rác trong một cấu trúc thư mục lồng nhau.

Tôi đã thử như sau:

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

Vấn đề là tạo ra đầu ra XML được định dạng trên màn hình, nhưng không thay đổi tệp.

Làm thế nào tôi có thể thay đổi lệnh này để nội dung tập tin thực tế được thay đổi?

Câu trả lời:


23

Điều này có thể được thực hiện từ findviệc sử dụng trực tiếp -exec:

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

Những gì được chuyển đến -execsẽ được gọi một lần cho mỗi tệp được tìm thấy với các tham số mẫu {}được thay thế bằng tên tệp hiện tại. Việc \;kết thúc lệnh find chỉ chấm dứt dòng.

Việc sử dụng xargskhông thực sự cần thiết trong trường hợp này bởi vì chúng ta cần phải gọi xmllintmột lần cho mỗi tệp vì cả tên tệp đầu vào và đầu ra phải được chỉ định trong cùng một lệnh gọi.

xargssẽ là cần thiết nếu lệnh được chuyển đến từ find đang hoạt động trên nhiều tệp cùng một lúc và danh sách đó dài. Bạn không thể làm điều đó trong trường hợp này, vì bạn cần chuyển tên tệp duy nhất cho --outputtùy chọn xmllint. Nếu không, xargsbạn có thể gặp phải lỗi "Danh sách đối số quá dài" nếu bạn đang xử lý nhiều tệp. xargscũng hỗ trợ chuỗi thay thế tập tin với -Itùy chọn:

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

Sẽ làm tương tự như find -execlệnh trên. Nếu bất kỳ thư mục nào của bạn có ký tự lẻ trong không gian như bạn sẽ cần sử dụng các -0tùy chọn findxargs. Nhưng sử dụng xargsvới -Ingụ ý tùy chọn -L 1có nghĩa là chỉ xử lý 1 tệp tại một thời điểm, do đó bạn cũng có thể sử dụng trực tiếp findvới -exec.


@manatwork cảm ơn vì đã chỉnh sửa - dính ngón tay; o)
didster

Tôi chỉ chạy cái này và nó xuất hiện để điều trị! Rất cám ơn cho câu trả lời nhanh chóng và súc tích!
Harry

2
“Điều này sẽ thất bại nếu danh sách tập tin là quá lớn”: Không, nó sẽ không thất bại (nó xử lý một tập tin duy nhất tại một thời gian), và trong thực tế find … -execlà cách trực tiếp nhất để làm điều này.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles Điểm tốt! Tôi đã cập nhật câu trả lời của tôi cho phù hợp.
didster

1
Điều này hoạt động do thực tế là xmllinttrước tiên tải tài liệu xml đầy đủ vào bộ nhớ và chỉ sau đó phân tích / ghi ra. Điều này cho phép xử lý tài liệu tại chỗ.
gavenkoa

6

Tôi thường tấn công những vấn đề này với một lớp gián tiếp. Viết một kịch bản shell thực hiện những gì bạn muốn và gọi nó. Tôi muốn đề xuất như một sự khởi đầu

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

Hãy dùng thử trên một hoặc hai tệp bằng tay, sau đó bạn có thể thay thế nó trong xargs

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

Đây có vẻ là một cách tiếp cận tốt nếu tôi cần phải thực hiện các thao tác phức tạp hơn trong tương lai. Cảm ơn vì sự trả lời.
Harry
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.