dd: nhiều tập tin đầu vào


13

Tôi cần ghép các đoạn từ hai tệp:

nếu tôi cần nối toàn bộ tập tin, tôi chỉ có thể làm

cat file1 file2 > output

Nhưng tôi cần bỏ qua 1 MB đầu tiên từ tệp đầu tiên và tôi chỉ muốn 10 MB từ tệp thứ hai. Âm thanh như một công việc cho dd.

dd if=file1 bs=1M count=99 skip=1 of=temp1
dd if=file2 bs=1M count=10 of=temp2
cat temp1 temp2 > final_output

Có một khả năng để làm điều này trong một bước? tức là không cần lưu kết quả trung gian? Tôi có thể sử dụng nhiều tập tin đầu vào ddkhông?

Câu trả lời:


21

dd có thể viết vào stdout quá.

( dd if=file1 bs=1M count=99 skip=1
  dd if=file2 bs=1M count=10  ) > final_output

Đây có lẽ là cách tốt nhất. Tệp đầu ra không bị đóng / mở lại (giống như với oflag=append conv=notrunc), vì vậy các hệ thống tệp bị phân bổ chậm (như XFS) ít có khả năng quyết định tệp được thực hiện khi còn nhiều việc phải làm.
Peter Cordes

@PeterCordes đó là một điểm tốt, nhưng miễn ddlà không được yêu cầu sync, phân bổ bị trì hoãn không nên khởi động ngay lập tức (trừ khi bộ nhớ bị thắt chặt trong trường hợp không phương thức nào sẽ hoãn phân bổ).
Stephen Kitt

@StephenKitt: Có lẽ bạn đúng. Tôi đã nghĩ đến việc phân bổ đầu cơ của XFS , nơi nó cần phát hiện đặc biệt mẫu truy cập đóng / mở lại (đôi khi được nhìn thấy cho các tệp nhật ký).
Peter Cordes

3
Trong các shell như thế bashmkshkhông tối ưu hóa ngã ba cho lệnh cuối cùng trong một lớp con, bạn có thể làm cho nó hiệu quả hơn một chút bằng cách thay thế lớp con bằng một nhóm lệnh. Đối với các shell khác, điều đó không quan trọng, và cách tiếp cận subshell thậm chí có thể hiệu quả hơn một chút vì shell không cần lưu và khôi phục thiết bị xuất chuẩn.
Stéphane Chazelas

10

Tôi không nghĩ rằng bạn có thể dễ dàng đọc nhiều tệp trong một lệnh ddgọi, nhưng bạn có thể nối thêm để xây dựng tệp đầu ra theo một số bước:

dd if=file1 bs=1M count=99 skip=1 of=final_output
dd if=file2 bs=1M count=10 of=final_output oflag=append conv=notrunc

Bạn cần chỉ định cả hai conv=notruncoflag=append. Cái đầu tiên tránh cắt ngắn đầu ra, cái thứ hai bắt đầu ghi từ cuối tập tin hiện có.


8

Ghi nhớ rằng ddlà một giao diện thô đến read(), write()lseek()cuộc gọi hệ thống. Bạn chỉ có thể sử dụng nó một cách đáng tin cậy để trích xuất các khối dữ liệu khỏi các tệp thông thường, các thiết bị chặn và một số thiết bị ký tự (như /dev/urandom), đó là các tệp read(buf, size)được đảm bảo trả về sizemiễn là không đạt đến cuối tệp.

Đối với đường ống, ổ cắm và hầu hết các thiết bị ký tự (như ttys), bạn không có sự đảm bảo nào trừ khi bạn có read()kích thước 1 hoặc sử dụng ddphần mở rộng GNU iflag=fullblock.

Vì vậy:

{
  gdd < file1 bs=1M iflag=fullblock count=99 skip=1
  gdd < file2 bs=1M iflag=fullblock count=10
} > final_output

Hoặc là:

M=1048576
{
  dd < file1 bs=1 count="$((99*M))" skip="$M"
  dd < file2 bs=1 count="$((10*M))"
} > final_output

Hoặc với hệ vỏ có hỗ trợ dựng sẵn cho toán tử tìm kiếm như ksh93:

M=1048576
{
  command /opt/ast/bin/head -c "$((99*M))" < file1 <#((M))
  command /opt/ast/bin/head -c "$((10*M))" < file2
}

Hoặc zsh(giả sử bạn headhỗ trợ -ctùy chọn ở đây):

zmodload zsh/system &&
{
  sysseek 1048576 && head -c 99M &&
  head -c 10M < file2
} < file1 > final_output

Bạn có thực sự cần báo giá? Kết quả luôn luôn là một số nguyên?
Steven Penny

@StevenPenny, bỏ phần mở rộng không được yêu cầu đang yêu cầu trình phân tách + toàn cầu, điều này sẽ không có ý nghĩa gì ở đây. Phần tách được thực hiện trên giá trị hiện tại của $IFS. Đó là bất kể nội dung của biến / mở rộng. Xem thêm Ý nghĩa bảo mật của việc quên trích dẫn một biến trong vỏ bash / POSIX
Stéphane Chazelas

@ Stéphane Chazelas - trong ví dụ đầu tiên, bạn đang sử dụng gddthay vì dd. Đó là một lỗi đánh máy, hay đó là cố ý?
Martin Vegter

3

Với một bash ism và chức năng "sử dụng con mèo vô dụng ", nhưng gần nhất với cú pháp mà OP sử dụng:

cat <(dd if=file1 bs=1M count=99 skip=1) \
    <(dd if=file2 bs=1M count=10) \
   > final_output

(Điều đó đang được nói, câu trả lời của Stephen Kitt dường như là phương pháp hiệu quả nhất có thể.)


3
Nói đúng ra, <(...)là một kshism mà cả zshbashsao chép.
Stéphane Chazelas
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.