странное поведение при использовании рекурсии в ksh93

Я столкнулся с некоторыми проблемами в ksh93 при рекурсивном просмотре каталогов.

создать несколько файлов и каталогов.

base=/tmp/nonsens

for i in {1..3}
do
    mkdir -p ${base}/dir${i}
    for j in {1..2}
    do
        mkdir ${base}/dir${i}/dir${j}
        touch ${base}/dir${i}/dir${j}/file${j}
        touch ${base}/dir${i}/file${j}
    done
done

Сейчас прохожу через скрипт ksh93.

rdir ()
{
    typeset dir=$1

    for file in `ls $dir`
    do
        if [ -d $dir/$file ]
        then
            echo "Directory: $dir/$file"
            rdir $dir/$file
        else
            echo "File     : $dir/$file"
        fi
    done
}   

rdir /tmp/nonsens

создаст этот вывод в ksh93

cheko@chwiclu1:~> rdir /tmp/nonsens
Directory: /tmp/nonsens/dir1
Directory: /tmp/nonsens/dir1/dir1
File     : /tmp/nonsens/dir1/dir1/file1
File     : /tmp/nonsens/dir1/dir1/dir2
File     : /tmp/nonsens/dir1/dir1/file1
File     : /tmp/nonsens/dir1/dir1/file2
File     : /tmp/nonsens/dir1/dir1/dir2
File     : /tmp/nonsens/dir1/dir1/dir3

при использовании pdksh/bash создаст это

cheko@redcube:~$ rdir /tmp/nonsens
Directory: /tmp/nonsens/dir1
Directory: /tmp/nonsens/dir1/dir1
File     : /tmp/nonsens/dir1/dir1/file1
Directory: /tmp/nonsens/dir1/dir2
File     : /tmp/nonsens/dir1/dir2/file2
File     : /tmp/nonsens/dir1/file1
File     : /tmp/nonsens/dir1/file2
Directory: /tmp/nonsens/dir2
Directory: /tmp/nonsens/dir2/dir1
File     : /tmp/nonsens/dir2/dir1/file1
Directory: /tmp/nonsens/dir2/dir2
File     : /tmp/nonsens/dir2/dir2/file2
File     : /tmp/nonsens/dir2/file1
File     : /tmp/nonsens/dir2/file2
Directory: /tmp/nonsens/dir3
Directory: /tmp/nonsens/dir3/dir1
File     : /tmp/nonsens/dir3/dir1/file1
Directory: /tmp/nonsens/dir3/dir2
File     : /tmp/nonsens/dir3/dir2/file2
File     : /tmp/nonsens/dir3/file1
File     : /tmp/nonsens/dir3/file2

Кто-нибудь знает обходной путь? Или существует переключатель, который заставляет ksh93 вести себя как надо?


person cheko    schedule 30.11.2009    source источник


Ответы (2)


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

В FAQ по ksh93 говорится в части III (Сценарии оболочки):

Q18. В чем разница между именем функции и именем()?

А18. В кш88 такие же были. Однако стандарт POSIX выбирает foo() для функций и определяет для них семантику System V Release 2, чтобы не было локальных переменных и ловушки не попадали в область действия. ksh93 сохраняет семантику ksh88 для функций, определенных как имя функции, и изменил семантику name(), чтобы она соответствовала семантике POSIX. Ясно, что имя функции более полезно.

У меня нет доступа к оболочке ksh93, чтобы проверить это, но подразумевается, что когда вы вызываете функцию rdir из самой себя, переменная dir перезаписывается. Итак, основываясь на вышеизложенном, попробуйте объявить свою функцию как function rdir, чтобы получить семантику ksh88 с переменными в локальной области.

person Chris J    schedule 30.11.2009

идеально!

function rdir
{
    typeset dir=$1

    for file in `ls $dir`
    do
        if [ -d $dir/$file ]
        then
            echo "Directory: $dir/$file"
            rdir $dir/$file
        else
            echo "File     : $dir/$file"
        fi
    done
}

rdir /tmp/nonsens

делает работу. Спасибо.

person cheko    schedule 30.11.2009