LoC별로 파일 정렬 - wc -l에서 파이프할 때 정렬이 작동하지 않습니다.

LoC별로 파일 정렬 - wc -l에서 파이프할 때 정렬이 작동하지 않습니다.

LoC별로 파일 디렉터리를 정렬하려고 합니다.

그러나 sort라인을 파이프로 연결하면 아무 일도 하지 않는 것 같습니다.

paths=`find ./src/ | egrep "\.(cpp|h)$"`
for path in $paths; do
wc -l $path | sort -n;
done

결과는 다음과 같습니다(선주문순으로 정렬되지만 find숫자 wc는 무시됩니다).

50 /a/a.cpp
10 /a/a.h
200 /b/b.cpp
13 /b/b.h
...

파이프 대신 파일에 정렬을 사용하는 경우:

for path in $paths; do
wc -l $path >> test.txt;
done

sort -n test.txt

그것하다일하다:

```bash
10 /a/a.h
13 /b/b.h
50 /a/a.cpp
200 /b/b.cpp
...

파이프라인 버전이 작동하지 않는 이유는 무엇입니까?

답변1

각각 wc의 출력을 개별적으로 , 로 sort파이프합니다 . 루프의 전체 출력을 처리하기 위해 파이프를 이동하면 다음과 같이 작동합니다.

paths=`find ./src/ | egrep "\.(cpp|h)$"`
for path in $paths; do
wc -l $path
done | sort -n

find출력을 반복하는 것을 피해야 합니다 .;또한 필터링된 출력 egrep에 사용할 필요가 없습니다 . find다음을 사용하여 위의 모든 작업을 처리할 수 있습니다.

find ./src/ \( -name '*.cpp' -o -name '*.h' \) -exec wc -l {} \; | sort -n

또는 "전체" 행이 있어도 괜찮다면 더 효율적으로,

find ./src/ \( -name '*.cpp' -o -name '*.h' \) -exec wc -l {} + | sort -n

(파일 이름에 개행 문자가 포함되어 있으면 여전히 잘 작동하지 않습니다.)

답변2

첫 번째 루프는 wc -l각 루프의 단일 라인 출력을 개별적으로 정렬하고 차례로 출력합니다. 작동하지 않습니다(예상된 결과입니다!).

두 번째 접근 방식은 먼저 wc모든 통화에 대한 모든 회선을 집계한 다음 정렬합니다. 이것이 올바른 접근 방식입니다. 중간에 파일이 있는지 여부는 여기서 문제가 되지 않습니다. 문제는 첫 번째 루프에서 실제로 아무것도 정렬하지 않는다는 것입니다.

그래서,

( for path in $paths; do
wc -l $path
done ) | sort -n

작동해야합니다.

귀하의 find호출은 egrep을 사용하여 출력을 필터링하기 때문에 이상합니다(예: CMake 빌드에서 때때로 찾을 수 있듯이 .cpp로 끝나는 폴더와 마찬가지로 흥미로운 결과로 이어짐). find -type f '(' -iname '*.cpp' -o -iname '*.h' ')'그러나 나는 권장하지 않습니다. find공백(매우 일반적임), 개행 문자 등이 포함된 파일 이름은 아무 이유 없이 모두 깨질 수 있으므로 여기에서 모두 함께 사용합니다 .

대신 쉘(내 추측으로는 bash)이 직접 제공하는 것을 사용하십시오.

shopt -s nullglob ## don't fail on empty globs
shopt -s globstar

for path in **/**.{h,cpp} ; do
  wc -l "${path}"
done | sort -n

실제로 더 짧게 만들 수도 있습니다.

shopt -s nullglob ## don't fail on empty globs
shopt -s globstar
wc -l **/*.{h,cpp} | sort -n

답변3

findwc및 유틸리티의 GNU 구현 에서는 head파일 경로에 개행 문자가 포함되어 있지 않다고 가정합니다.

{
  find . '(' -name '*.h' -o -name '*.cpp' ')' -print0
  printf '%s\0' /dev/null
} |
  wc -l --files0-from=- |
  head -n -2 | # remove up to 2 trailing lines to remove the /dev/null
               # and possibly "total" lines
  sort -n

-exec wc -l {} +"전체" 행만 출력되도록 보장하는 이 방법과 대조적입니다 .

여러 파일이 전달되면 한 줄만 출력되는 문제가 여전히 있습니다 wc. total여기서는 추가 콘텐츠를 추가 /dev/null하고 마지막에 제거하여 이 문제를 해결합니다.

관련 정보