The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



Индекс форумов
Составление сообщения

Исходное сообщение
"Рекурсивный обход поддерикторий"
Отправлено Аноним, 18-Окт-14 23:47 
Fix.
#!/bin/sh

NUM=10
BIG_LIST="${HOME}/BigList";
SHORT_LIST="${HOME}/ShortList";

discover() {
    cd "${1}";
    DIR="${PWD}";

    for FILE in .* *; do
        if [ "${FILE}" = "." -o "${FILE}" = ".." ]; then
            continue;
        fi

        if [ -d "${FILE}" ]; then
            # Включая директории.
            # COUNT=$((${COUNT:-0}+1));
            if [ ! -x "${FILE}" ]; then
                echo 1>&2 "${FILE}: no execute (or search) permission on file";
            else
                (discover "${FILE}");
            fi
        else
            COUNT=$((${COUNT:-0}+1));
        fi
    done
    
    if [ "${COUNT:-0}" -gt "${NUM}" ]; then
        echo "${DIR}" >> "${BIG_LIST}";
    else
        echo "${DIR}" >> "${SHORT_LIST}";
    fi
}

if [ -z "${*}" ]; then
    set "${PWD}";
fi

for DIR in "${@}"; do
    if [ ! -e "${DIR}" ]; then
        echo 1>&2 "${DIR}: No such file ir directory";
        continue;
    fi
    
    if [ ! -d "${DIR}" ]; then
        echo 1>&2 "${DIR} is a file, not a directory";
        continue;
    fi
    
    (discover "${DIR}");    
    
done

Проверяем, были ли переданы параметры скрипту.
if [ -z "${*}" ]; then
    set "${PWD}";
fi

${*} - все позиционные параметры одной строкой
$ script.sh a b c
«a» - первый позиционный параметр, $1.
«b» - второй позиционный параметр, $2.
«c» - третий позиционный параметр, $3.
$ a() { echo "\$1 = $1, \$2 = $2, \$3 = $3, \$* = $*"; }
$ a a b c

Если строка пустая, то это означает, что скрипту не были переданы параметры
$ a() { if [ -z "${var}" ]; then  echo "var is empty"; else echo "var is $var"; fi }
$ a
$ var="text"
$ a
$ unset var
$ a


Логичнее использовать
if [ $# -gt 0 ]; then
    …
fi

$# - количество позиционных параметров.


Если скрипту не переданы параметры, то сохраняем абсолютный путь к текущей директории в первом позиционном параметре.

# Удалим все позиционные параметры.
$ shift $#
$ if [ -z "${1}" ]; then  echo "\$1 is empty"; else echo "\$1 is $1"; fi
$ set "${PWD}"
$ if [ -z "${1}" ]; then  echo "\$1 is empty"; else echo "\$1 is $1"; fi


Переменная $PWD всегда содержит абсолютный путь к текущей директории.
Нет необходимости выполнять команду pwd.

for DIR in "${@}"; do
    …
done

Сохраняем (поочерёдно) значение каждого позиционного параметра в переменную DIR.
$ set /tmp/dir "/tmp/d i r" /tmp
$1 - /tmp/dir
$2 - /tmp/d i r
$3 - /tmp

$ for DIR in "${@}"; do echo "\$DIR id ${DIR}"; done

"${@}" - экранируется (цитируется, ориг. quoting), поскольку в именах директорий (файлов) могут содержаться «специальные символы» (например, пробелы).

Сравните результат.
$ set /tmp/dir "/tmp/d i r" /tmp
$ for DIR in "${@}"; do echo "\$DIR id ${DIR}"; done
$ for DIR in ${@}; do echo "\$DIR id ${DIR}"; done


Проверяем, существует ли файл.

    if [ ! -e "${DIR}" ]; then
        echo 1>&2 "${DIR}: No such file ir directory";
        continue;
    fi


Вывод сообщения об ошибке:

echo 1>&2 "${DIR}: No such file ir directory";

перенаправляем в stderr (поток номер 2).

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

    
Проверяем, является ли файл директорией.

    if [ ! -d "${DIR}" ]; then
        echo 1>&2 "${DIR} is a file, not a directory";
        continue;
    fi

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

То есть если скрипту в качестве параметры передан файл, а не директория, то мы сообщаем об этом и переходим к следующему параметру.

Вызываем функцию discovery в subshell, передав значение переменной DIR.
$ a() { echo "\$1 is $1"; }
$ a /tmp

Нужно использовать «экранирование».
Сравните результат.
$ a() { echo "\$1 is $1"; }
$ a "/tmp/d i r"
$ a /tmp/d i r

Нам нужен отдельный счётчик для каждой директории, для этого мы используем subshell (В bash, можно использовать массив).

Сравните результат.
$ a() { var="$1"; echo "var is $var"; }
$ unset var
$ echo $var
$ (a text)
$ echo $var
$ a text
$ echo $var


discover() {
    # Переходим в директорию.
    cd "${1}";

    DIR="${PWD}";

    # Сохраняем (поочерёдно) имя каждого файла (в директории) в переменную FILE.
    # Нам нужно обработать все файлы, в том числе и скрытые.
    # Сравните результат.
    # $ mkdir /tmp/dir
    # $ touch /tmp/dir/.file
    # cd /tmp/dir
    # $ ls .*
    # $ ls *
    for FILE in .* *; do
        # Игнорируем родительский каталог ".."
        # Игнорируем «синоним» для текущей директории "."
        # $ mkdir /tmp/dir
        # $ cd /tmp/dir
        # «..» - /tmp
        # «.» - /tmp/dir
        # Если значение переменной FILE равно «..» или «.»
        if [ "${FILE}" = "." -o "${FILE}" = ".." ]; then
            # Переходим к следующим файлу (возвращаемся в начала цикла).
            continue;
        fi

        # Проверяем, является ли файл директорией.
        if [ -d "${FILE}" ]; then
            # Включая директории.
            # COUNT=$((${COUNT:-0}+1));
            # Проверяем, есть ли у текущего пользователя право на выполнение (поиск), если нет, то мы не сможем в неё перейти.
            if [ ! -x "${FILE}" ]; then
                echo 1>&2 "${FILE}: no execute permission on file";
            else
                (discover "${FILE}");
            fi
        else
            # Инкрементируем счётчик.
            # Если, переменная COUNT не имеет значения, то подставляем 0.
            COUNT=$((${COUNT:-0}+1));
        fi
    done
    
    # Если значение счётчика больше значения переменной NUM.
    if [ "${COUNT:-0}" -gt "${NUM}" ]; then
        echo "${DIR}" >> "${BIG_LIST}";
    else
        echo "${DIR}" >> "${SHORT_LIST}";
    fi
}


 

Ваше сообщение
Имя*:
EMail:
Для отправки новых сообщений в текущей нити на email укажите знак ! перед адресом, например, !user@host.ru (!! - не показывать email).
Более тонкая настройка отправки ответов производится в профиле зарегистрированного участника форума.
Заголовок*:
Сообщение*:
  Введите код, изображенный на картинке: КОД
 
При общении не допускается: неуважительное отношение к собеседнику, хамство, унизительное обращение, ненормативная лексика, переход на личности, агрессивное поведение, обесценивание собеседника, провоцирование флейма голословными и заведомо ложными заявлениями. Не отвечайте на сообщения, явно нарушающие правила - удаляются не только сами нарушения, но и все ответы на них. Лог модерирования.



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру