Как получить количество файлов в папке в виде переменной? - программирование
Подтвердить что ты не робот

Как получить количество файлов в папке в виде переменной?

Используя bash, как можно получить количество файлов в папке, исключая каталоги из оболочки script без запроса интерпретатора?

С помощью друга я пробовал

$files=$(find ../ -maxdepth 1 -type f | sort -n)
$num=$("ls -l" | "grep ^-" | "wc -l")

который возвращается из командной строки:

../1-prefix_blended_fused.jpg: No such file or directory
ls -l :  command not found
grep ^-: command not found
wc -l:   command not found

соответственно. Эти команды работают в командной строке, но НЕ с bash script.

Учитывая файл, заполненный файлами изображений, отформатированными как 1-pano.jpg, я хочу захватить все изображения в каталоге, чтобы получить самый большой нумерованный файл для последующего обработки на следующем обработанном изображении.

Почему расхождение?

4b9b3361

Ответ 1

Кавычки вызывают сообщения об ошибках.

Чтобы узнать количество файлов в каталоге:

shopt -s nullglob
numfiles=(*)
numfiles=${#numfiles[@]}

который создает массив, а затем заменяет его количеством элементов. Это будет включать файлы и каталоги, но не точечные файлы или . или .. или другие точечные каталоги.

Используйте nullglob, чтобы пустой каталог давал счет 0 вместо 1.

Вместо этого вы можете использовать find -type f или подсчитать каталоги и вычесть:

# continuing from above
numdirs=(*/)
numdirs=${#numdirs[@]}
(( numfiles -= numdirs ))

Также см. "Как найти самый последний (самый новый, самый ранний, самый старый) файл в каталоге?"

Вы можете иметь столько пробелов, сколько хотите внутри блока исполнения. Они часто помогают в удобочитаемости. Единственным недостатком является то, что они делают файл немного больше и могут немного замедлить первоначальный анализ (только). Есть несколько мест, которые должны иметь пробелы (например, около [, [[, ], ]] и = в сравнениях), и несколько мест, которые не должны (например, около = в назначении).

Ответ 2

ls -l | grep -v ^d | wc -l

Одна строка.

Ответ 3

Как насчет:

count=$(find .. -maxdepth 1 -type f|wc -l)
echo $count
let count=count+1 # Increase by one, for the next file number
echo $count

Обратите внимание, что это решение неэффективно: оно создает дочерние оболочки для команд find и wc, но оно должно работать.

Ответ 4

file_num=$(ls -1 --file-type | grep -v '/$' | wc -l)

это немного легче, чем команда find, и подсчитывает все файлы текущего каталога.

Ответ 5

Избавьтесь от котировок. Оболочка обрабатывает их как один файл, поэтому ищет "ls -l".

Ответ 6

Простой эффективный метод:

#!/bin/bash
RES=$(find ${SOURCE} -type f | wc -l)

Ответ 7

Самый простой и надежный способ, который я могу придумать, - использовать команду find для создания надежно исчисляемого результата.

Подсчет количества выводимых символов find с помощью wc:

find . -maxdepth 1 -type f -printf '.' | wc --char

или длина строки вывода find:

a=$(find . -maxdepth 1 -type f -printf '.')
echo ${#a}

или используя вывод find для заполнения арифметического выражения:

echo $(($(find . -maxdepth 1 -type f -printf '+1')))

Ответ 8

Перемотайте qoutes, и вы будете в порядке

Ответ 9

Развернувшись на принятом ответе (Деннис W): когда я пробовал этот подход, у меня были неправильные подсчеты для dirs без subdirs в Bash 4.4.5.

Проблема заключается в том, что по умолчанию nullglob не установлен в Bash, а numdirs=(*/) устанавливает массив 1 элемента с шаблоном glob */. Аналогично, я подозреваю, что numfiles=(*) будет иметь 1 элемент для пустой папки.

Настройка shopt -s nullglob, чтобы отключить nullglobbing, разрешает проблему для меня. Для отличной дискуссии о том, почему nullglob по умолчанию не установлен на Bash, см. Ответ здесь: Почему nullglob не используется по умолчанию?

Примечание. Я бы прокомментировал ответ напрямую, но не имел точек репутации.

Ответ 10

Вот один из способов сделать это как функцию. Примечание: вы можете передать этот пример, dirs for (количество каталогов), файлы для подсчета файлов или "all" для подсчета всего в каталоге. Не пересекает дерево, поскольку мы не собираемся этого делать.

function get_counts_dir() {

    # -- handle inputs (e.g. get_counts_dir "files" /path/to/folder)
    [[ -z "${1,,}" ]] && type="files" || type="${1,,}"
    [[ -z "${2,,}" ]] && dir="$(pwd)" || dir="${2,,}"

    shopt -s nullglob
    PWD=$(pwd)
    cd ${dir}

    numfiles=(*)
    numfiles=${#numfiles[@]}
    numdirs=(*/)
    numdirs=${#numdirs[@]}

    # -- handle input types files/dirs/or both
    result=0
    case "${type,,}" in
        "files")
            result=$((( numfiles -= numdirs )))
        ;;
        "dirs")
            result=${numdirs}
        ;;
        *)  # -- returns all files/dirs
            result=${numfiles}
        ;;

    esac

    cd ${PWD}
    shopt -u nullglob

    # -- return result --
    [[ -z ${result} ]] && echo 0 || echo ${result}
}

Примеры использования функции:

folder="/home"
get_counts_dir "files" "${folder}"
get_counts_dir "dirs" "${folder}"
get_counts_dir "both" "${folder}"

Напечатает что-то вроде:

2
4
6