질문
파일로 가득 찬 git 저장소가 있는데 대부분은 텍스트입니다.
있는지 알고 싶습니다.
n
다음으로 끝나는 파일의 코드 줄.py
m
다음으로 끝나는 파일의 코드 줄.md
o
다음으로 끝나는 파일의 코드 줄.yaml
p
파일의 코드 줄확장자 없음- 등
노트:
- 재귀적으로 실행하고 싶습니다. 폴더 내부를 확인하세요.
.git
최상위 폴더의 디렉터리를 제외하고 싶습니다.- 바이너리 파일을 무시하는 것이 가능할 것 같습니다(확장자가 없는 일부 텍스트 파일과 확장자가 없는 일부 바이너리 파일이 있습니다).
- 대소문자를 구분하고 싶습니다. 그룹
.csv
.CSV
- 빈 줄(또는 빈 줄만)을 무시하고 싶습니다.
- 나와 같은 파일이 있는 경우
myfile.yaml.j2
그룹.j2
또는.yaml.j2
.
답변1
이 시도:
find ./ -not -path "./.git/*" -type f -exec wc -l {} + |
awk '{print tolower($0)}' |
sed -e '$ d' |
sed -e "s#/.*/##g" |
sed -e "s/\./ \./g" |
awk '
{ if ( NF <= 2 ) { count["none"] += $1 } else { count[$NF] += $1 } }
{ next }
END { for (group in count) printf("%d%s%s\n", count[group], OFS, group) }
' |
sort -n
분할:
find ./
이 디렉터리에서 개체를 반복적으로 검색합니다.-not -path "./.git/*"
들어오지 못하게 하다.git
-type f
디렉토리 대신 파일-exec wc -l {} +
각 파일에 대해 단어 개수 유틸리티(wc
)를 실행합니다. 여기에는 빈 줄이 포함되어 있으므로 질문의 모든 요구 사항을 충족하지 않습니다.awk '{print tolower($0)}'
소문자로 되다sed -e '$ d'
모든 파일의 줄 합계인 마지막 줄을 제거합니다.sed -e "s#/.*/##g"
예를 들어, 삭제된 파일의 경로는 확장자가 아니라 확장자가a/something.egg/blah
없는 것으로 계산되어야 합니다..egg/blah
sed -e "s/\./ \./g"
파일 확장자가 자체 단어가 되도록 검색/.
바꾸기.
awk '{ if ( NF <= 2 ) { count["none"] += $1 } else { count[$NF] += $1 } } { next } END { for (group in count) printf("%d%s%s\n", count[group], OFS, group) }'
이것은 큰 문제입니다.awk
강력하지만 매우 날카롭지는 않습니다.count
사전이다if (NF <= 2)
"단어"가 3개 미만인 경우 확장자가 없습니다.count["none"] += $1
사전의 요소를 증분합니다. 키는 문자열 리터럴입니다none
. 첫 번째 단어인 파일의 줄 수를 추가하여 증분합니다.$1
count[$NF] += $1
사전에 요소를 추가합니다. 키는$NF
(줄의 마지막 단어)이며 확장자는$1
(줄의 첫 번째 단어)는 파일의 줄 수입니다.{ next }
모든 행에 대해 반복for (group in count)
루프for
, 인라인printf(...)
number extension
예를 들어 출력 문자열의 형식을 ;로 지정합니다123 .abc
(으로 끝나는 파일에 123줄이 있는 경우.abc
).
sort -n
결과를 오름차순으로 정렬합니다.-n
문자열이 아닌 숫자로 정렬하는 것을 의미합니다.
답변2
내가 올바르게 이해하고 테스트가 양호하다면 다음을 권장합니다(숨겨진 디렉터리와 파일을 건너뛰고 싶다고 가정하고 그렇지 않은 경우 알려주시기 바랍니다).
shopt -s globstar
declare -A arr
for f in test/**; do
# if a directory, skip
[[ -d "$f" ]] && continue
lines=0
# strip the extension
ext="${f##*.}"
# convert it to lowercase
ext="${ext,,}"
# if no dot in the name, extension is "empty"
[[ ! $(basename "$f") =~ \. ]] && ext="empty"
# count the lines
lines=$(wc -l "$f"| cut -d' ' -f1)
# if lines equals to 0, skip
[[ $lines -eq 0 ]] && continue
# append the number of line to the array
lines=$(( "${arr[$ext]}"+$lines ))
arr[$ext]=$lines
done
# loop over the array
for n in ${!arr[@]}; do
echo "files $n: total lines ${arr[$n]}"
done
출력(예제 파일에서):
files yaml: total lines 3
files md: total lines 3
files empty: total lines 4
files csv: total lines 6
files py: total lines 5
답변3
이해하기 쉽도록 함수별로 나누었습니다.
#!/bin/bash
# For the next two functions, we will use "-print0", which will print out \0 instead of \n.
# This will help prevent whitespace problems when piping the filenames into xargs.
find_extension()
{
find "$1" -type f -name "*.$2" -print0 2>/dev/null
}
find_no_extension()
{
find "$1" -type f -regex '^.*/[^.]+$' -print0 2>/dev/null
}
concat_files()
{
xargs -0 cat
}
delete_empty_lines()
{
sed -E '/^[[:space:]]*$/d'
}
line_count_of_files()
{
concat_files | delete_empty_lines | wc -l
}
print_usage()
{
echo "Usage: $0 [EXTENSION]... [SEARCH_DIRECTORY]";
}
NUMBER_OF_EXTENSIONS=$(($# - 1))
SEARCH_DIR="${*: -1}"
if [ $# -lt 2 ];
then
echo "Not enough parameters.";
print_usage;
exit 1;
fi
if ! [ -d "$SEARCH_DIR" ];
then
echo "$SEARCH_DIR does not exist, or is not a directory."
print_usage;
exit 1;
fi
for EXTENSION in "${@:1:$NUMBER_OF_EXTENSIONS}";
do
printf ".$EXTENSION: %s\n" $(find_extension "$SEARCH_DIR" "$EXTENSION" | line_count_of_files)
done
printf "No extension: %s\n" $(find_no_extension "$SEARCH_DIR" | line_count_of_files)
이는 검색하려는 파일 확장자를 지정할 수 있는 일반적인 스크립트에 가깝습니다. 하지만 항상 확장자가 없는 파일을 검색합니다.
파일에 저장하고 실행 권한을 부여한 후 PATH에 넣어야 합니다. 이름을 count_lines.sh로 지정한다고 가정해 보겠습니다. 다음과 같이 호출할 수 있습니다 count_lines.sh py md yaml ~/Code
. 그러면 디렉토리에서 ~/Code
, 및 로 끝나는 파일과 확장자가 전혀 없는 파일을 검색합니다. 검색할 확장자를 원하는 만큼 선택할 수 있습니다. 최소한 하나가 있는지 확인하세요..py
.md
.yaml