1

I wrote a quick shell script to emulate the situation of xkcd #981 (without hard links, just symlinks to parent dirs) and used a recursive function to create all the directories. Unfortunately this script does not provide the desired result, so I think my understanding of the scope of variable $count is wrong.

How can I properly make the function use recursion to create twenty levels of folders, each containing 3 folders (3^20 folders, ending in soft links back to the top)?

#!/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
4

2 回答 2

1

试试这个(脚本的修改版本)——它似乎对我有用。不过,我拒绝测试到 20 个级别。在 8 级深度,三个顶级目录中的每一个在 Mac 文件系统上占用大约 50 MB。

#!/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 行为传递给函数的位置参数 ( $1and ) 命名——该符号仅表示如果您省略传递参数,您会从 shell(或子 shell)收到错误消息并退出。$2${1:?}$1

括号本身(上面的第 13 和 18 行)表示中间的命令在子 shell 中运行,因此子 shell 内目录的更改不会影响父 shell。

第 11 行的条件现在使用算术 ( -le) 而不是字符串<比较;这对于深度嵌套更有效(因为<是字典比较,所以第 9 级不小于第 10 级)。这也意味着可以[使用命令代替[[命令(虽然[[也可以使用,但我更喜欢老式的表示法)。

于 2013-08-28T21:16:32.107 回答
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
于 2013-08-28T21:20:39.513 回答