-1

Я пытаюсь подсчитать количество файлов в каталоге, одновременно проверяя подкаталоги с помощью того же самого скрипта и суммируя результаты.

#!/bin/bash

var=0

var=$(ls -l $1 | grep "^-" | tr -s ' ' | cut -d ' ' -f 9 | wc -l)

 for x in `ls -lr $1 | grep "^d" | tr -s ' ' | cut -d ' ' -f 9`;
  do
        output="$($0 $x)"
        var=$((var+output)) 
 done
echo $var

Однако я не получаю правильный результат.

Что я делаю неправильно?

2 ответа2

2

Чтобы найти общее количество обычных файлов в каталоге $1 и его подкаталогах:

find "$1" -type f -printf "1\n" | wc -l

Чтобы сохранить это число в переменной:

var=$(find "$1" -type f -printf "1\n" | wc -l)

Это будет работать, даже если имена файлов или каталогов содержат пробелы или другие сложные символы.

обсуждение

Давайте рассмотрим эту строку из исходного кода:

 for x in `ls -lr $1 | grep "^d" | tr -s ' ' | cut -d ' ' -f 9`;

Во-первых, никогда не следует разбирать ls. Это ненадежно. Вывод ls меняется с одной версии на другую. Кроме того, из-за способа обработки специальных символов имя, отображаемое с помощью ls , не обязательно является правильным именем файла или каталога.

Во-вторых, при использовании переменных оболочки, таких как $1 , они должны быть в двойных кавычках. В противном случае на них выполняется разбиение слов и расширение пути, что может привести ко всему набору ошибок.

В-третьих, в такой форме, как:

for x in `...`

оболочка выполнит разбиение слов и расширение имени пути в результате подстановки команды. Это также может привести ко всему множеству ошибок.

1

... Я не получаю правильный результат.  Что я делаю неправильно?

  1. Я не знаю; Ваш скрипт работает на меня (в очень ограниченном тестировании).
  2. John1234 обсуждает проблемы с вашим подходом.

... я все еще пытаюсь сделать это по-своему

Вот адаптация вашего сценария, который работает (для меня) и использует более безопасные механизмы:

#!/bin/bash

var=0
shopt -s nullglob

for x in "$1"/*
 do
      if [ -d "$x" ]
      then
            output="$($0 "$x")"
            var=$((var+output))
      else
            var=$((var+1))
      fi
 done
echo $var

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

(shopt -s nullglob предназначен для работы с каталогами, в которых нет содержимого.)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .