2013-08-28 5 views
1

Я написал сценарий быстрой оболочки для эмуляции ситуации xkcd #981 (без жестких ссылок, только символических ссылок на родительские директории) и использовал рекурсивную функцию для создания всех каталогов. К сожалению, этот скрипт не дает желаемого результата, поэтому я считаю, что мое понимание области переменной $ count неверно.Сценарий оболочки: переменная область видимости в функциях

Как правильно заставить функцию использовать рекурсию для создания двадцать уровней папок, каждая из которых содержит 3 папки (3^20 папок, заканчивающихся мягкими ссылками вверх)?

#!/bin/bash 
echo "Generating folders:" 
toplevel=$PWD 
count=1 
GEN_DIRS() { 
for i in 1 2 3 
do 
     dirname=$RANDOM 
     mkdir $dirname 
     cd $dirname 
     count=$(expr $count + 1) 
     if [ $count < 20 ] ; then 
       GEN_DIRS 
     else 
       ln -s $toplevel "./$dirname" 
     fi 
done 
} 
GEN_DIRS 
exit 

ответ

1

Попробуйте эту (измененную версию сценария) - она ​​работает для меня. Однако я отказываюсь тестировать до 20 уровней; на 8 уровнях в глубину каждая из трех каталогов верхнего уровня занимает около 50 МБ в файловой системе Mac.

#!/bin/bash 
echo "Generating folders:" 
toplevel=$PWD 
GEN_DIRS() 
{ 
    cur=${1:?} 
    max=${2:?} 
    for i in 1 2 3 
    do 
     dirname=$RANDOM 
     if [ $cur -le $max ] 
     then 
      (
      echo "Directory: $PWD/$dirname" 
      mkdir $dirname 
      cd $dirname 
      GEN_DIRS $((cur+1)) $max 
      ) 
     else 
      echo "Symlink: $PWD/$dirname" 
      ln -s $toplevel "./$dirname" 
     fi 
    done 
} 

GEN_DIRS 1 ${1:-4} 

Строки 6 и 7 дают имена позиционных параметров ($1 и $2) передается в функцию - ${1:?} обозначение просто означает, что если опустить передать параметр $1, вы получите сообщение об ошибке от shell (или под-оболочкой), и он завершает работу.

Скобки сами по себе (строки 13 и 18 выше) означают, что команды между ними выполняются в под-оболочке, поэтому изменения в каталоге внутри под-оболочки не влияют на родительскую оболочку.

Условие в строке 11 теперь использует арифметику (-le) вместо строки < сравнения; это лучше работает для глубокой вложенности (потому что < является лексикографическим сравнением, поэтому уровень 9 не меньше уровня 10). Это также означает, что команда [ в порядке используется вместо команды [[ (хотя [[ также будет работать, я предпочитаю старомодную нотацию).

+0

линии шесть/семь настраивает пес и максимум на один и четыре я беру это? Кроме того, почему у парни около 14-19? Отличное решение, спасибо! – CliffordSR

+0

К сожалению, не создавая все каналы прямо сейчас. Когда вызывается с 1 и 20, он создает 4 уровня в глубину и только одну символическую ссылку в конечном каталоге вместо 3:/ – CliffordSR

+0

4 уровня были жестко закодированы при вызове GEN_DIRS. Символы 1 против 3 означали непонимание этого требования. Оба вопроса теперь исправлены. С помощью скрипта под названием 'gendirs.sh' запуск' bash gendirs.sh' создает 4 уровня, а 'bash gendirs.sh 8' генерирует 8 уровней и т. Д. –

0

Я в конечном итоге создать сценарий вроде этого:

#!/bin/bash 

echo "Generating folders:" 

toplevel=$PWD 

level=0 
maxlevel=4 

function generate_dirs { 
    pushd "$1" >/dev/null || return 
    ((++level)) 
    for i in 1 2 3; do 
     dirname=$RANDOM 
     if ((level < maxlevel)); then 
      echo "$PWD/$dirname" 
      mkdir "$dirname" && generate_dirs "$dirname" 
     else 
      echo "$PWD/$dirname (link to top)" 
      ln -sf "$toplevel" "$dirname" 
     fi 
    done 
    popd >/dev/null 
    ((--level)) 
} 

generate_dirs . 

exit 
+0

Работает отлично, но я не могу сказать, что все это понимаю. Вы можете объяснить строку 11? Вы удаляете аргумент, с которым вы вызвали функцию? И тогда почему последние две строки функции? – CliffordSR

+0

Кроме того, двадцать потребовалось бы намного дольше, чем я думал: P – CliffordSR

+0

@CliffordSR См. 'Help pushd' для получения дополнительной информации. '>/dev/null' отправляет вывод в значение null, чтобы сделать его тихим. И '|| return' завершает функцию, если она не может перейти в этот каталог. Аргумент - это каталог. Код безопасен. Если что-то не удается по неизвестной причине, оно не будет проходить бесконечный цикл или создавать материалы в каталоге, который не должен быть им. – konsolebox

Смежные вопросы