рекурсивный подсчет строк в файлах, группировка по расширению файла

Мое решение (, используемое ежедневно ), заключается в использовании aliasдля xdg-open.

Просто наденьте это на~/.bashrc:

alias open='xdg-open '

Затем закройте и перезапустите оболочку или source ~/.bashrc.

Теперь с помощью этой команды можно открыть любой файл... от.png до.jpg, от.docx до.pdf и.txt.

0
01.05.2020, 08:32
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, а также файлы без расширения вообще. Вы можете выбрать любое количество расширений для поиска, просто убедитесь, что у вас есть хотя бы одно.

1
28.04.2021, 23:16

Попробуйте это

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" search/replace. with. `, поэтому расширение файла — это собственное слово
  • 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 }повторить для всех строк, то, что после nextсделать только один раз
    • for (group in count)цикл for, встроенный
    • printf(...)отформатировать выходную строку как 123.abc(, если в файлах 123 строки, заканчивающиеся на.abc)
  • sort -nсортировать результаты в порядке возрастания, -nозначает сортировать как число, а не строку
3
28.04.2021, 23:16

Если я вас правильно понял, и мои тесты хороши, я предлагаю это (при условии, что вы хотите пропустить скрытые каталоги и файлы, скажите мне, если это не так):

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
1
28.04.2021, 23:16

Теги

Похожие вопросы