$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 -abo
OR을 사용하여 가능한 바이트 오프셋 후보를 찾을 수도 있지만 strings -t d
이는 찾고 있는 실제 패턴에 따라 다릅니다. 이는 수천 번의 호출(섹터당 하나) 대신 하나의 프로그램 호출로 전체 콘텐츠를 검색할 수 있다는 장점이 있습니다.
모든 작업을 대신 수행하는 명령줄 유틸리티를 찾지 않는 한, 요구 사항에 대해 전체 내용을 한 번에 검색하는 작은 C/Go/Python 스크립트를 이길 수는 없습니다...
귀하의 스크립트 아이디어도 물론 작동하지만 이는 dd
루프 내에서 다시 호출하여 한 번에 한 블록씩 stdin을 읽는 것을 의미하며 이는 아마도 이전보다 느릴 것입니다...read
답변2
이 split
명령을 사용하여 파일의 인접한 청크에 대해 "필터"를 실행하고 , 를 사용하여 필터를 작성할 수 있습니다 cmp
. 그러면 성공적인 일치 항목마다 개행 문자를 가져온 다음 해당 일치 항목을 계산하는 데 사용됩니다. 예를 들어 파일, 템플릿 블록 파일 및 템플릿 블록 의 크기인 경우 다음 명령줄과 같을 수 있습니다.echo
true
wc
$F
$TB
$SZ
$ split -b $SZ --filter="cmp $TB >& /dev/null && echo ; true" $F | wc -l
이렇게 true
하면 필터 명령줄 성공이 보장되며, 입력을 절약하기 위해 대신 사용할 수 있습니다. :
단, 가독성이 향상되지는 않습니다.
cmp
또한 반환 코드만 관심이 있으므로 모든 출력(예: stdout 및 stderr) 의 리디렉션에 유의하세요 .