递归脚本中的目录深度



嗨,我想在我的 Linux bash 作业中获得一些帮助。 我必须制作一个脚本来获取一个目录并返回最深子目录的深度(+1 对于每个目录)。 我必须递归地这样做。 我必须使用"list_dirs.sh"来获取可存活的目录并回显其子目录。

这就是我到目前为止得到的:

dir=$1
sub=`source list_dirs.sh`
((depth++)) 
for i in $sub
do
if [ -n "$sub" ] ; then
./depthScript $dir/$i
fi
done
if ((depth > max)) ; then
max=$depth
echo $max
fi

在使用支持返回 3 的 dir 进行测试后,我得到了:

1
1
1
1

似乎我的深度计数器忘记了以前的值,我得到了输出 每个目录..需要一些帮助!

您可以使用 bash 函数来创建递归函数调用。

理想情况下,您的函数会在没有子目录的目录上调用0回显,并在存在某些子目录$subdir的情况下回显1+$(getDepth $subdir)。有关框架的 bash 中的递归函数,请参阅此问题。

当你正常运行一个脚本时(即它在你的PATH中,你只需输入它的名字,或者你输入一个明确的路径,如./depthScript),它作为当前shell的子进程运行。这很重要,因为每个过程都有自己的变量。变量也有两种:shell变量(仅在该进程中可用)和环境变量(其值导出到子进程,但不从子进程中备份)。根据您希望变量值可用的位置,有三种不同的方法来定义它们:

# By default, variables are shell variable that's only defined in this process:
shellvar=something
# `export` puts a variable into the environment, so it'll be be exported to subprocesses.
# You can export a variable either while setting it, or as a separate operation:
export envvar=something
export anotherenvvar
anotherenvvar=something
# You can also prefix a command with a variable assignment. This makes an
# environment variable in the command process's environment, but not the current
# shell process's environment:
prefixvar=something ./depthScript $dir/$i

鉴于上述任务:

  • shellvar在当前 shell 进程中定义,但不在任何其他进程(包括为运行 depthScript 而创建的子进程)中定义。
  • envvaranotherenvvar将由子流程(及其子流程以及后续命令的所有子流程)继承,但在这些子流程中对其所做的任何更改在当前进程中完全不起作用。
  • prefixvar仅在为运行 depthScript(及其子进程)而创建的子进程中可用,但在当前 shell 进程或其任何其他子进程中不可用。

简短总结:由于过程结构,这是一团糟,因此最好避免尝试在变量中的脚本之间传递值(或对同一脚本的不同调用)。使用环境变量进行设置,以便您希望正式发布(但不需要更改太多)。对脚本的特定调用的本地内容使用 shell 变量。

那么,您应该如何传递深度值?好吧,标准方法是让每个脚本(或命令)将其输出打印为"标准输出",然后使用该脚本的任何内容都可以将其输出捕获到文件(command >outfile)或变量(var=$(command))。在这种情况下,我推荐后者:

depth=$(./depthScript "$dir/$i")
if ((depth > max)) ; then
max=$depth
fi

其他一些建议:

  • 考虑您的控制和数据流。当前脚本遍历所有子目录,然后在最后对最深的子目录进行一次检查。但是您需要单独检查每个子目录,看看它是否比当前最大值更深,并在最后报告其中最深的子目录。
  • 双引号您的变量引用(就像我在上面的"$dir/$i"所做的那样)。不带引号的变量引用会受到单词拆分和通配符扩展的影响,这是许多悲伤的根源。看起来您需要不$sub引号,因为您需要将其拆分为单词,但这会使脚本无法处理带有空格的目录名称。请参阅 BashFAQ #20:"如何查找并安全地处理包含换行符、空格或两者的文件名?
  • if [ -n "$sub" ] ; then测试无关紧要。如果$sub为空,则循环将永远不会运行。
  • 在 shell 脚本中,相对路径(如./depthScript)相对于父进程的任何工作目录,而不是相对于脚本的位置。如果有人从另一个目录运行您的脚本,./depthScript将不起作用。请改用"$BASH_SOURCE"。请参阅 BashFAQ #28:"如何确定脚本的位置?我想从同一个地方读取一些配置文件。
  • 尝试对脚本进行故障排除时,将set -x放在麻烦的部分之前会有所帮助。这使 shell 在运行时打印每个命令,以便您可以看到发生了什么。
  • 通过 shellcheck.net 运行脚本 - 它会指出许多常见错误。

最新更新