찾기: 조건이 있는 여러 "-exec"

찾기: 조건이 있는 여러 "-exec"

설명한 대로 Windows에서 Linux 드라이버로 변환하는 과정의 일부로 stdint.h단어가 포함된 파일에 표준 C 패키지를 포함하려고 합니다.LARGE_INTEGER여기데이터 유형의 경우. find 및 xargs에 대한 이전 스레드에 대해 알고 있습니다.여기그리고여기.

GNU 찾기 부분의 코드는 주로 다음을 기반으로 합니다.철사:

gfind /tmp/ -type f                                                      \
    \( -name "*.h" -o -name "*.cpp" \)                                   \
    -exec ggrep -Pl "LARGE_INTEGER" {} +

의사코드 확장자도 포함하고 싶습니다. 또한 파일에 다음 단어가 포함되어야 합니다.LARGE_INTEGER

gfind /tmp/ -type f                                                \
    \( -name "*.h" -o -name "*.cpp" \)                             \
    -and -exec ggrep -Pl "LARGE_INTEGER" {} \;                     \
    | xargs gsed -i '1s/^/#include <stdint.h>\n/'

잘 모르겠어서 -and주는 곳

gsed: can't read /tmp/: No such file or directory
...

나는 commandlinefu의 예를 따랐습니다.여기.

새 명령을 GNU SED 기반 조회에 어떻게 결합합니까?

답변1

나는 다음과 같은 두 가지 작업 find에 1을 사용합니다.-exec

찾다. -유형 f -exec grep -qFSOME_STRING{} \; -sed 실행'주문하다'{} \;

두 번째 명령은 첫 번째 명령이 다음과 같이 평가되는 경우에만 실행됩니다.진짜종료 코드 0따라서 sed문제의 파일은 파일에 다음이 포함된 경우에만 처리됩니다.SOME_STRING. 작동 방식을 쉽게 확인할 수 있습니다.

찾다. -유형 f -exec grep -qFSOME_STRING{} \; -인쇄

다음을 포함하는 파일만 나열해야 합니다.SOME_STRING. 물론, 항상 두 개 이상의 표현식을 연결하고 !(부정)과 같은 연산자를 사용할 수도 있습니다. 예를 들면 다음과 같습니다.

찾다. -유형 f -exec grep -qF이것{} \; -exec grep -qF저것{} \; -인쇄

다음을 포함하는 파일만 나열됩니다.이것하지만 포함하지 않습니다저것.
어쨌든 귀하의 경우에는 다음과 같습니다.

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) \
-exec ggrep -qF LARGE_INTEGER {} \; \
-exec gsed -i '1s/^/#include <stdint.h>\n/' {} \;

1
나는 당신이 지원 하거나 선택 xargs하지 않는다고 가정합니다 . 그렇다면 다음 구성을 사용하십시오.-0--null

찾다. -유형 f -exec grep -lFZSOME_STRING{} + | xargs -0 gsed -s -i '주문하다'

즉, 귀하의 경우:

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) \
-exec ggrep -lFZ LARGE_INTEGER {} + | \
xargs -0 gsed -s -i '1s/^/#include <stdint.h>\n/'

첫 번째 것보다 더 효율적이어야 합니다.
또한 둘 다 모든 유형의 파일 이름에서 작동합니다. 더 빠르기 때문에 grep( 고정 문자열)을 사용하고 있으므로 -F정규식을 사용할 계획이라면 제거하십시오.

답변2

출력을 gfind다음으로 파이프하면 됩니다 xargs.

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -exec ggrep -l "LARGE_INTEGER" {} + | xargs sed -i '1s/^/#include <stdint.h>\n/'

고정 문자열과 일치하기 때문에 해당 -P옵션을 제거했습니다 .ggrep

그러나 이 솔루션은 개행 문자가 포함된 파일 이름을 잘 처리하지 못합니다. 더 안전한 접근 방식은 gfindNULL로 끝나는 파일 이름을 강제로 출력하고 루프에서 출력을 반복하는 것입니다 while.

#!/bin/bash

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -print0 | while read -d '' -r filepath; do
    [ "$(ggrep -l "LARGE_INTEGER" "$filepath")" ] && sed -i '1s/^/#include <stdint.h>\n/' "$filepath"
done

독립 실행형 버전이 마음에 드신다면:

gfind /tmp/ -type f \( -name "*.h" -o -name "*.cpp" \) -print0 | while read -d '' -r filepath; do [ "$(ggrep -l "LARGE_INTEGER" "$filepath")" ] && sed -i '1s/^/#include <stdint.h>\n/' "$filepath"; done

관련 정보