Как создать рекурсивный вызов функции в unix

Как создать рекурсивный вызов функции в unix
#!/bin/sh
checking()
{
  cd "$1"
  for D in *;do
    if [ -d "$D" ]; then
      cd "$D"
      for d in *;do
        echo "$d"
        if [ -d "$d" ]
        then
           `checking() $d`
        fi
        if [ -f "$d" ]
        then
                file_name=`echo "$d" | cut -d'.' -f1`
                echo $file_name
                file_ext=$(echo $d |awk -F . '{if (NF>1) {print $NF}}')
                echo $file_ext
                if [ $file_ext = bin ]
                then
                        strings $d > $file_name.txt
                        mv $file_name.txt /somepath
                fi
        fi

      done
      cd ..

    fi
  done
}

a=$(pwd)
checking() $a

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

Я пробовал использовать рекурсивный вызов функции, но этот вызов не срабатывает. Пожалуйста, помогите.

решение1

Я отмечаю несколько вещей в вашей функции:

  • Вы переходите в каталог, затем перебираете файлы, затем делаете и то, и другоеснова( cd; for d in *; do cd; for d in * ...). Похоже, что это пропустит каждый второй уровень дерева каталогов во время рекурсивного обхода. Одной итерации по файлам должно быть достаточно
  • Я не думаю, что вам нужно использовать подоболочку при рекурсивном вызове функции (есть подстановка команды backtick в `checking() $d`). Это может быть полезно, если вам нужны переменные, локальные для каждого экземпляра вызова функции, но многие оболочки могут делать это напрямую (используя localв Bash,по-видимому typesetв ksh93)
  • И, конечно же, синтаксис вызова функции: если hi() { echo "hello $1"; }мы запускаем ее как любую другую команду, просто с помощью hi "$name".
  • Мы можем отменить awkи использовать оболочкурасширение параметрачтобы выбрать расширение файла. (но проверьте пограничный случай, когда в имени файла нет точки.) Или используйтеcase "$f" in *.bin) ...

Вот довольно простая функция для обхода дерева каталогов:

#!/bin/sh

walk() {
        cd "$1"
        for f in *; do 
                if [ -d "$f" ] ; then
                        echo descending into "$f"...
                        walk "$f"
                else
                        ext=${f##*.}
                        if [ "$ext" = "bin" ] ; then
                                echo "found .bin file: $f"
                        fi
                fi

        done
        cd ..
}

walk .

(Хотя следует отметить, что cd "$dir"; ... ; cd ..структура может вызвать проблемы, если кто-то переместит каталог прямо в тот момент, когда программа обрабатывает этот каталог. Ссылка ..изменится, и возврат по ней продолжится из нового местоположения, которое может даже находиться за пределами исходного дерева. Мы могли бы обойти это, используя абсолютные имена путей все время или pushd/popd(в Bash), или поместив всю функцию или ее вызовы в подоболочки.)

Связанный контент