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
find
wc
및 유틸리티의 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
하고 마지막에 제거하여 이 문제를 해결합니다.