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 xargs
trong trường hợp chiều dài dòng lệnh vượt quá ARG_MAX
và 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).
bash
cầu. Mặt khác, tôi không thấy bất kỳ trường hợp nào xargs
hoặc cat
sẽ không cư xử như mong đợi.
xargs
sẽ 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=always
tệ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 ( python
hoặ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 fd
là 0
dà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 1
chuyể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ổ.
dd
hoặc thông qua việc đọc.
fallocate
sẽ phủ nhận chi phí phụ find
, mặc dù nó sẽ nhanh hơn trong lần thứ hai. btrfs
chắc chắn mở ra một số khả năng thú vị mặc dù.
find
không sắp xếp các tệp giống như shell toàn cầu.