我知道我可以使用更简单的“找到”来完成以下任务。评论,但我试图使用递归调用实现解决方案。我正在查看特定目录并尝试获取所有子目录中任何文件名的最大长度。但是,我的递归只能降低一级,所以它基本上会返回某个目录或其中的最长文件名。子目录。
#! /bin/bash
export maxlen=0
findmaxr()
{
if [ $# -eq 0 ] ; then
echo "Please pass arguments. Usage: findmax dir"
exit -1
fi
if [ ! -d "$1" ]; then
echo "No such directory exist."
exit -2
fi
for file in $(/bin/ls $1)
do
if [ -d "$file" ] ; then
findmaxr $file # Recursively call the method for subdirectories
else
cur=${#file}
if [ $maxlen -lt $cur ] ; then
maxlen=$cur
fi
fi
done
echo "The file with the longest name has [$maxlen] characters."
}
findmaxr `pwd`
答案 0 :(得分:2)
这里有几个问题。最大的是[ -d "$file" ]
和findmaxr $file
,file
变量只包含文件的名称,而不是整个路径。所以,如果你在/ dir中,并且/ dir / sub / sub2存在,那么顶级将运行findmaxr /dir
(这很好),它将运行findmaxr sub
(这是有效的,但不是'真的是你想要的),然后运行findmaxr sub2
(根本不起作用)。因此,一种可能性是在这些行中使用"$1/$file"
,但还有另一个问题:parsing ls
is a bad idea and will fail for some directory names。最好使用没有解析问题的for path in "$1"/*
(前提是你引用了所有变量引用,无论如何都要引用它)和为你提供了完整的路径,所以你不必预先$1/
。但是,在检查文件名长度之前,你必须剥离路径的前面,例如local file="$(basename "$path")"
。
第二个问题是它在完成每个目录后打印$maxlen
,而不是在扫描整个树之后。要解决此问题,只需在运行findmaxr
后将该命令从递归函数移出到主序列。
还有另一个更微妙的问题:file
(cur
和path
如果你遵循我的建议)不是局部变量,这意味着递归调用可以改变它们的值而不是调用findmaxr
的实例。您应该将它们声明为局部变量以避免混淆。哦,没有必要导出maxlen
- 它将自动在脚本中全局,并且它与您正在运行的任何命令无关(export
将其传递给它)。
答案 1 :(得分:2)
findmaxr的每个实例都需要返回它找到的maxlen(通过echo),你需要在比较中包含该输出。
还有另一个问题:假设a
,b
和c
是目录,d.txt
是一个文件,它们按如下方式排列:{{1} }。从a/b/c/d.txt
内部运行脚本。当a
为file
时,b
为真,if [ -d "$file" ]
被调用。它会调用findmaxr b
,而ls b
会导致findmaxr c
,导致ls c
... ls c
失败,因为您仍然在a
。你需要cd
到子目录或者包括整个路径,如下所示:$1/$file
。
这是修复了这些问题的脚本:
#!/bin/bash
findmaxr()
{
if [ $# -eq 0 ] ; then
echo "Please pass arguments. Usage: findmax dir"
exit -1
fi
if [ ! -d "$1" ]; then
echo "No such directory exist."
exit -2
fi
maxlen=0
for file in $(/bin/ls "$1")
do
if [ -d "$1/$file" ] ; then
cur=`findmaxr "$1/$file"` # Recursively call the method for subdirectories
else
cur=${#file}
fi
if [ $maxlen -lt $cur ] ; then
maxlen=$cur
fi
done
echo $maxlen
}
maxlen=$(findmaxr $(pwd))
echo "The file with the longest name has [$maxlen] characters."