'find'를 'xargs wc'로 파이프 출력하면 총계가 비합리적입니다.

'find'를 'xargs wc'로 파이프 출력하면 총계가 비합리적입니다.

수천 개의 파일이 있는 프로젝트에서 전체 코드 줄을 PHP(CSS, JavaScript 등 제외)의 코드 줄과 비교하고 싶었습니다.

내가 달릴 때

find . -type f | xargs wc -l

마지막 줄의 합계는 다음과 같습니다.낮추다내가 달릴 때보다

find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l

두 번째 파일이 find첫 번째 파일보다 더 작은 파일 목록(엄격한 하위 집합)이어야 한다는 점을 고려하면 두 번째 경우에 더 높은 총계를 find어떻게 보고할 수 있습니까 ?wc

답변1

xargs통과할 수 밖에 없다 ARG_MAX에 대한 인수 바이트입니다 wc.

내 Mac에서 ARG_MAX는 전체 파일 이름과 전체 프로젝트 파일의 상대 경로보다 작습니다.첫 번째명령을 실행하여 xargs결과를 덤프했습니다 find.wc 두 배치로, 이는 다음을 의미합니다 wc.총 2개, 수천 개의 파일 이름으로 둘러싸여 있습니다. 그러나 ARG_MAX는 우연히두번째 find출력되므로 두 번째로 작은 찾기가 모두 표시되었습니다.하나 wc총.

수정 사항은 다음 명령을 사용하여 (지루한) 개별 파일 수 줄 없이 모든 합계를 볼 수 있도록 하는 것이었습니다.

find . -type f | xargs wc -l | grep total
find -E . -regex '.+\.(php|inc)' -type f | xargs wc -l | grep total

그런 다음 여러 "총" 행을 손으로 합산합니다.

답변2

이를 수행하는 방법에는 여러 가지가 있지만 xargs최선은 아닙니다. 다음은 몇 가지입니다.

  1. 가장 간단한 방법은 cat각 파일을 찾아 find행 수를 계산하는 것입니다. 주의하세요. 파일 이름에 공백이나 이상한 문자가 없는 경우에만 작동합니다.

    find . -type f | while read n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while read n; do cat $n; done | wc -l 
    

    파일 이름에 이상한 문자(슬래시, 공백 등)가 포함될 가능성이 있으면 대신 다음을 사용하십시오.

    find . -type f | while IFS= read -r n; do cat $n; done | wc -l
    find -E . -regex '.+\.(php|inc)' -type f | while IFS= read -r n; do cat $n; done | wc -l 
    
  2. 더 좋은 방법은 find -exec옵션을 사용하는 것입니다.

    find . -name "*.pep" -exec cat {} \; | wc
    find -E . -regex '.+\.(php|inc)' -type f -exec cat {} \; | wc
    

답변3

awk출력 의 다양한 "총" 수를 합산하는 데 사용됩니다 wc -l!

(참고: wc -l개행 문자 수를 반환합니다. 즉, 마지막 문자가 없는 마지막 "줄"은 계산되지 않습니다. 이는 또는 \n의 경우와 같습니다 .)awksed

export LC_ALL=C
find . -type f -print0 | xargs -0 wc -l | 
    awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'


# xargs alternatives using: find ... -exec <wc|awk|sed> ... '{}' +
#man find | less -p '{} \+'

# wc
find . -type f -exec wc -l '{}' + 2>/dev/null | 
   awk '/^ *[[:digit:]]+ total$/{ total+=$1 }END{print total}'

# awk
find . -type f -exec awk 'END {print NR}' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

# sed
find . -type f -exec sed -n '$=' '{}' + 2>/dev/null | 
    awk '{ total+=$1 }END{print total}'

관련 정보