Tôi đã có 10k + tệp có tổng cộng hơn 20 GB mà tôi cần ghép thành một tệp.
Có cách nào nhanh hơn
cat input_file* >> out
?
Cách ưa thích sẽ là lệnh bash, Python cũng được chấp nhận nếu không chậm hơn đáng kể.
Tôi đã có 10k + tệp có tổng cộng hơn 20 GB mà tôi cần ghép thành một tệp.
Có cách nào nhanh hơn
cat input_file* >> out
?
Cách ưa thích sẽ là lệnh bash, Python cũng được chấp nhận nếu không chậm hơn đáng kể.
Câu trả lời:
Không, mèo chắc chắn là cách tốt nhất để làm điều này. Tại sao sử dụng python khi có một chương trình đã được viết bằng C cho mục đích này? Tuy nhiên, tuy nhiên, bạn có thể muốn xem xét sử dụng xargstrong trường hợp chiều dài dòng lệnh vượt quá ARG_MAXvà bạn cần nhiều hơn một cat. Sử dụng các công cụ GNU, điều này tương đương với những gì bạn đã có:
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z |
xargs -0 cat -- >>out
findđược dẫn qua sort. Nếu không có điều này, các tệp sẽ được liệt kê theo thứ tự tùy ý (được xác định bởi hệ thống tệp, có thể là thứ tự tạo tệp).
bashcầu. Mặt khác, tôi không thấy bất kỳ trường hợp nào xargshoặc catsẽ không cư xử như mong đợi.
xargssẽ gọi khi có thể catđể tránh lỗi E2BIG của lệnh thực thi (2).
Phân bổ không gian cho tệp đầu ra trước tiên có thể cải thiện tốc độ chung vì hệ thống sẽ không phải cập nhật phân bổ cho mỗi lần ghi.
Chẳng hạn, nếu trên Linux:
size=$({ find . -maxdepth 1 -type f -name 'input_file*' -printf '%s+'; echo 0;} | bc)
fallocate -l "$size" out &&
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z | xargs -r0 cat 1<> out
Một lợi ích khác là nếu không có đủ không gian trống, bản sao sẽ không được thử.
Nếu bật btrfs, bạn có thể copy --reflink=alwaystệp đầu tiên (ngụ ý không có bản sao dữ liệu và do đó sẽ gần như tức thời) và nối thêm phần còn lại. Nếu có 10000 tệp, điều đó có lẽ sẽ không tạo ra nhiều khác biệt trừ khi tệp đầu tiên rất lớn.
Có một API để khái quát hóa rằng sao chép lại tất cả các tệp (nhưng BTRFS_IOC_CLONE_RANGE ioctl), nhưng tôi không thể tìm thấy bất kỳ tiện ích nào hiển thị API đó, vì vậy bạn phải thực hiện bằng C ( pythonhoặc các ngôn ngữ khác với điều kiện họ có thể gọi tùy ý ioctl) .
Nếu các tệp nguồn thưa thớt hoặc có các chuỗi ký tự NUL lớn, bạn có thể tạo một tệp đầu ra thưa thớt (tiết kiệm thời gian và dung lượng ổ đĩa) bằng (trên các hệ thống GNU):
find . -maxdepth 1 -type f -name 'input_file*' -print0 |
sort -z | xargs -r0 cat | cp --sparse=always /dev/stdin out
>hay >>, nhưng 1<>như tôi đã nói để viết vào tập tin.
<>là toán tử chuyển hướng đọc / ghi tiêu chuẩn Bourne / POSIX. Xem hướng dẫn sử dụng shell của bạn hoặc thông số POSIX để biết chi tiết. Mặc định fdlà 0dành cho <>toán tử ( <>viết tắt của từ 0<>, thích <là viết tắt 0<và >viết tắt 1>), vì vậy bạn cần 1chuyển hướng rõ ràng thiết bị xuất chuẩn. Ở đây, không quá nhiều đến mức chúng ta cần đọc + write ( O_RDWR), nhưng chúng ta không muốn O_TRUNC(như trong >) sẽ giải quyết những gì chúng ta vừa phân bổ.
ddhoặc thông qua việc đọc.
fallocatesẽ phủ nhận chi phí phụ find, mặc dù nó sẽ nhanh hơn trong lần thứ hai. btrfschắc chắn mở ra một số khả năng thú vị mặc dù.
findkhông sắp xếp các tệp giống như shell toàn cầu.