我正在尝试解析android源目录,我需要提取除某些模式之外的所有目录名称。如果您在下面注意到,现在我只在排除列表中包含了1个目录,但我将添加更多。,
find命令不会排除名为“docs”的目录。
注释掉的行有效,但另一行没有。为了便于调试,我包含了min和maxdepth,我将在以后删除它。
关于它为什么不起作用的任何评论或提示?
#! /bin/bash
ANDROID_PATH=$1
root=/
EXCLUDES=( doc )
cd ${root}
for dir in "${EXCLUDES[@]}"; do
exclude_name_cmd_string=${exclude_name_cmd_string}$(echo \
"-not -name \"${dir}*\" -prune")
done
echo -e ${exclude_name_cmd_string}
custom_find_cmd=$(find ${ANDROID_PATH} -mindepth 1 -maxdepth 1 \
${exclude_name_cmd_string} -type d)
#custom_find_cmd=$(find ${ANDROID_PATH} -mindepth 1 -maxdepth 1 \
# -not -name "doc*" -prune -type d)
echo ${custom_find_cmd}
答案 0 :(得分:4)
使用可能引用的参数构建命令字符串是个坏主意。你进入嵌套的引用级别和eval
以及一堆其他危险/混乱的句法内容。
使用数组构建find
;你已经将EXCLUDES合二为一了。
此外,重复的-not
和-prune
对我来说似乎很奇怪。我会把你的命令写成这样的东西:
excludes=()
for dir in "${EXCLUDES[@]}"; do
excludes+=(-name "${dir}*" -prune -o)
done
find "${ANDROID_PATH}" -mindepth 1 -maxdepth 1 "${excludes[@]}" -type d -print
结果是,您希望将-name
的参数作为find
扩展的文字通配符传递给find
,而不是shell扩展返回的文件列表,也不是包含文字引号的字符串。如果您尝试将命令构建为字符串,则很难做到这一点,但如果使用数组则很容易。
朋友不要让朋友将shell命令构建为字符串。
答案 1 :(得分:1)
当我将脚本(名为fin.sh
)运行为:
bash -x fin.sh $HOME/tmp
跟踪输出的一行是:
find /Users/jleffler/tmp -mindepth 1 -maxdepth 1 -not -name '"doc*"' -prune -type d
你看到双引号周围的单引号吗?那是bash
试图提供帮助。我猜你的“不工作”问题是你仍然得到输出中包含的doc*
下的目录;除此之外,它似乎对我有用。
如何解决这个问题?
...似乎你找到了解决这个问题的方法......我不确定我是否会相信Bourne shell(但是Korn shell似乎同意Bash),但看起来像它可能适用于Bash。我很确定这是在过去30年左右发生的变化,但很难证明这一点;掌握旧代码并不容易。
如果您重复排除目录,我也想知道您是否需要重复-prune
个选项;我对-prune
并不十分熟悉。
答案 2 :(得分:0)
发现问题。它与exclude_name_cmd_string中的转义序列。 应该是正确的语法
exclude_name_cmd_string=${exclude_name_cmd_string}$(echo \ "-not -name ${dir}* -prune")