dd의 효율적인 사용(여러 청크를 버퍼링하고 한 번에 하나씩 처리)

dd의 효율적인 사용(여러 청크를 버퍼링하고 한 번에 하나씩 처리)

$templateBlock파일이 주어지면 특정 크기의 입력 블록과 일치하는 블록 수를 검색해야 합니다 $blockSize.

dd이 작업을 수행하는 효율적인 방법은 무엇입니까? 아래 메서드는 dd너무 많이 호출되기 때문에 끔찍하고 느립니다.

while [ $i -lt $totalBlocks]; do
  dd if="$pathToFile" bs=$blockSize count=1 skip=$i | diff $templateBlock -
  # Increase $count if $? is 0
  # Increase $i by 1 
done

가장 좋은 접근 방식은 아마도 한 번에 읽는 모든 것을 dd읽고 처리하는 $totalSize것 입니다. $blockSize이렇게 하면 한 번만 호출하면 됩니다 dd. 즉, dd모든(또는 많은) 청크를 한 번에 읽고 각 청크를 한 번에 처리할 수 있습니다. 이것이 가능합니까?

어쩌면 다음과 같은 것일 수도 있습니다.

dd if="$pathToFile" bs=$blockSize | for-each-block {
  diff $templateBlock -
  # Update $count if $? is 0
}

이상적으로는 쉘 유틸리티를 사용하고 싶습니다.
즉, Python이나 이와 유사한 프로그램을 작성할 필요가 없다는 것입니다.

답변1

쉘 스크립트에서는 GNU diffutil을 사용하는 것이 가장 좋습니다 cmp. 데이터를 비교하고 오프셋을 건너뛸 수도 있으므로 --ignore-initial=SKIP1:SKIP2각 섹터 오프셋에 대해 실행할 수 있으며 발견된 첫 번째 차이에서 종료됩니다... 이는 반효율적이지만 실행하려는 경우 cmp여전히 많은 작업이 필요합니다. cmp각 부서에 전화해 보세요.

grep -aboOR을 사용하여 가능한 바이트 오프셋 후보를 찾을 수도 있지만 strings -t d이는 찾고 있는 실제 패턴에 따라 다릅니다. 이는 수천 번의 호출(섹터당 하나) 대신 하나의 프로그램 호출로 전체 콘텐츠를 검색할 수 있다는 장점이 있습니다.

모든 작업을 대신 수행하는 명령줄 유틸리티를 찾지 않는 한, 요구 사항에 대해 전체 내용을 한 번에 검색하는 작은 C/Go/Python 스크립트를 이길 수는 없습니다...

귀하의 스크립트 아이디어도 물론 작동하지만 이는 dd루프 내에서 다시 호출하여 한 번에 한 블록씩 stdin을 읽는 것을 의미하며 이는 아마도 이전보다 느릴 것입니다...read

답변2

split명령을 사용하여 파일의 인접한 청크에 대해 "필터"를 실행하고 , 를 사용하여 필터를 작성할 수 있습니다 cmp. 그러면 성공적인 일치 항목마다 개행 문자를 가져온 다음 해당 일치 항목을 계산하는 데 사용됩니다. 예를 들어 파일, 템플릿 블록 파일 및 템플릿 블록 의 크기인 경우 다음 명령줄과 같을 수 있습니다.echotruewc$F$TB$SZ

$ split -b $SZ --filter="cmp $TB >& /dev/null && echo ; true" $F | wc -l

이렇게 true하면 필터 명령줄 성공이 보장되며, 입력을 절약하기 위해 대신 사용할 수 있습니다. :단, 가독성이 향상되지는 않습니다.

cmp또한 반환 코드만 관심이 있으므로 모든 출력(예: stdout 및 stderr) 의 리디렉션에 유의하세요 .

관련 정보