bash 递归函数返回文件树的目录深度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4329369/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Recursive Function to Return Directory Depth of File Tree
提问by Jef
I'm trying to write a function that will traverse the file directory and give me the value of the deepest directory. I've written the function and it seems like it is going to each directory, but my counter doesn't seem to work at all.
我正在尝试编写一个函数,该函数将遍历文件目录并为我提供最深目录的值。我已经编写了该函数,看起来它会进入每个目录,但我的计数器似乎根本不起作用。
dir_depth(){
local olddir=$PWD
local dir
local counter=0
cd ""
for dir in *
do
if [ -d "$dir" ]
then
dir_depth "/$dir"
echo "$dir"
counter=$(( $counter + 1 ))
fi
done
cd "$olddir"
}
What I want it to do is feed the function a directory, say /home, and it'll go down each subdirectory within and find the deepest value. I'm trying to learn recursion better, but I'm not sure what I'm doing wrong.
我想要它做的是为函数提供一个目录,比如 /home,它会在每个子目录中找到最深的值。我正在尝试更好地学习递归,但我不确定我做错了什么。
采纳答案by DigitalRoss
Here is a version that seems to work:
这是一个似乎有效的版本:
#!/bin/sh
dir_depth() {
cd ""
maxdepth=0
for d in */.; do
[ -d "$d" ] || continue
depth=`dir_depth "$d"`
maxdepth=$(($depth > $maxdepth ? $depth : $maxdepth))
done
echo $((1 + $maxdepth))
}
dir_depth "$@"
回答by sorpigal
Obviously find should be used for this
显然 find 应该用于此
find . -type d -exec bash -c 'echo $(tr -cd / <<< ""|wc -c):' -- {} \; | sort -n | tail -n 1 | awk -F: '{print , }'
At the end I use awk to just print the output, but if that were the output you wanted it would be better just to echo it that way to begin with.
最后,我使用 awk 来打印输出,但如果这是您想要的输出,那么最好以这种方式开始。
Not that it helps learn about recursion, of course.
当然,这并不是说它有助于学习递归。
回答by kipkoan
Here's a one–liner that's pretty fast:
这是一个非常快的单线:
find . -type d -printf '%d:%p\n' | sort -n | tail -1
Or as a function:
或者作为一个函数:
depth()
{
find -type d -printf '%d:%p\n' | sort -n | tail -1
}
回答by Paused until further notice.
Just a few small changes to your script. I've added several explanatory comments:
只需对您的脚本进行一些小的更改。我添加了几个解释性评论:
dir_depth(){
# don't need olddir and counter needs to be "global"
local dir
cd -- "" # the -- protects against dirnames that start with -
# do this out here because we're counting depth not visits
((counter++))
for dir in *
do
if [ -d "$dir" ]
then
# we want to descend from where we are rather than where we started from
dir_depth "$dir"
fi
done
if ((counter > max))
then
max=$counter # these are what we're after
maxdir=$PWD
fi
((counter--)) # decrement and test to see if we're back where we started
if (( counter == 0 ))
then
echo $max $maxdir # ta da!
unset counter # ready for the next run
else
cd .. # go up one level instead of "olddir"
fi
}
It prints the max depth (including the starting directory as 1) and the first directory name that it finds at that depth. You can change the test if ((counter > max))to >=and it will print the last directory name it finds at that depth.
它打印最大深度(包括起始目录为 1)和它在该深度找到的第一个目录名称。您可以将测试更改if ((counter > max))为>=,它将打印在该深度找到的最后一个目录名称。
回答by Thomas T.
The AIX (6.1) findcommand seems to be quite limited (e.g. no printf option). If you like to list all directories up to a given depth try this combination of findand dirname. Save the script code as maxdepth.ksh. In comparison to the Linux find -maxdepthoption, AIX findwill not stop at the given maximum level which results in a longer runtime, depending on the size/depth of the scanned direcory:
AIX (6.1)find命令似乎非常有限(例如没有 printf 选项)。如果您想列出指定深度内的所有目录,请尝试使用find和 的组合dirname。将脚本代码保存为 maxdepth.ksh。与 Linux 查找-maxdepth选项相比,AIXfind不会在给定的最大级别停止,这会导致运行时间更长,具体取决于扫描目录的大小/深度:
#!/usr/bin/ksh
# Param 1: maxdepth
# Param 2: Directoryname
max_depth=0
netxt_dir=
while [[ "$netxt_dir" != "/" ]] && [[ "$netxt_dir" != "." ]]; do
max_depth=$(($max_depth + 1))
netxt_dir=$(dirname $netxt_dir)
done
if [ -lt $max_depth ]; then
ret=1
else
ret=0
ls -d
fi
exit $ret
Sample call:
示例调用:
find /usr -type d -exec maxdepth.ksh 2 {} \;
回答by Matthew Flaschen
The traditional way to do this is to have dir_depthreturn the maximum depth too. So you'll return both the name and depth.
这样做的传统方法也是dir_depth返回最大深度。因此,您将返回名称和深度。
You can't return an array, struct, or object in bash, so you can return e.g. a comma-separated string instead..
您不能在 bash 中返回数组、结构或对象,因此您可以返回例如逗号分隔的字符串。
dir_depth(){
local dir
local max_dir=""
local max_depth=0
for dir in /*
do
if [ -d "$dir" ]
then
cur_ret=$(dir_depth "$dir")
cur_depth=$(expr "$cur_ret" : '\([^,]*\)')
cur_dir=$(expr "$cur_ret" : '.*,\(.*\)')
if [[ "$cur_depth" -gt "$max_depth" ]]; then
max_depth="$cur_depth"
max_dir="$cur_dir"
fi
fi
done
max_depth=$(($max_depth + 1))
echo "$max_depth,$max_dir"
}
EDIT: Fixed now. It starts with the directory you passed in as level 1, then counts upwards. I removed the cd, as it isn't necessary. Note that this will fail if filenames contain commas.
编辑:现在修复。它从您作为级别 1 传入的目录开始,然后向上计数。我删除了cd,因为它不是必需的。请注意,如果文件名包含逗号,这将失败。
You might want to consider using a programming language with more built-in data structures, like Python.
您可能需要考虑使用具有更多内置数据结构的编程语言,例如 Python。

