对于作业,我应该编写一个 bash 脚本,它可以充当非常基本的 bash 脚本find
,但无需实际使用该find
命令。例如,如果我输入以下内容:
my_find ~/homedir/ -name 'test*' -name '*.o' -type f
我需要它来搜索与通配符名称~/homedir/
匹配的任何内容,然后在这些结果中搜索与名称匹配的任何内容,最后(尽管可能是多余的)仅搜索文件。最后,它会列出所有结果。test*
AND
*.o
到目前为止,我已经创建了一个存储目录路径(dirpath=$1
)的变量。然后我用shift
它来摆脱第一个参数,然后执行此操作(请注意,-type
尚未实现):
while (($#)); do
if [[ $1 == "-name" ]]; then
# process the name here?
shift 2 # get rid of -name "name"
fi
done
我有点想知道如何构建甚至做到这一点。我有一个部分完成的函数,它将通过目录路径递归,但我不确定如何/在哪里处理传入的参数。这是查看每个目录的递归函数。
recurse_path () {
for i in "$@"; do
# process and store matching file names in the array?
if [[ -d "${i}" ]]; then
cd "${i}"
recurse_path *
fi
done
}
那么,在使用此函数时,如何搜索匹配的文件名并将结果存储在数组中呢?另外,这是执行此操作的正确方法,还是有可能更简单的方法来更新我在查看每个命令时获得的结果?我是 bash 脚本的新手,所以我将不胜感激任何建议。
答案1
让我尝试点一些基本的东西。
1.
如果我们已经可以遍历目录树,下一步就是在当前访问的目录中进行搜索。这取决于我们想要支持什么风格的模式语法。正则表达式是完全不同的事情。也许我们对 shell 内置的模式语法感到满意。那么这样就可以了。
for i in * ; do for p in <patterns> ; do
if [[ $i == $p ]]
...
fi
done ; done
2.
为了解析命令行,bash有内置的getopts,请参阅手册。
3.
对于数组,请参阅手册。
答案2
一个肮脏的解决方案看起来像:
boolRememberNext=0
rememberString=""
for arg in $*; do
if [ ${boolRememberNext} -eq 1 ]; then
rememberString="${rememberString} ${arg}"
fi
if [ "${arg}" = "-name" ]; then
boolRememberNext=1
else
boolRememberNext=0
fi
done
echo ${rememberString} | while read filemask; do
unquotedFile=$(echo "$filemask" | tr -d "'")
ls -R1 ~/homedir/ | grep ":" | cut -d: -f1 | while read dir; do
ls ${dir}/unquotedFile
done
done
为什么会脏呢?
- 很多循环,文件系统被访问很多次
- 忽略不正确的命令行语法
- 目录和文件名中不能有 :
- 用 tr 取消对 var 的引用将无法处理 * 组合
我不想为此使用 eval
可以采取哪些措施来改进解决方案?
您可以将中间结果存储在本地变量中,改进特殊字符的处理并检查语法。
您还可以执行 als ~/homedir/*
并向搜索路径添加星号,直到找不到文件。通过一些过滤器解析所有文件(awk?)。检查您找到的文件,它们是文件,而不是目录。