Bash 为查找建立命令字符串

Bash 为查找建立命令字符串,bash,shell,Bash,Shell,我正在尝试解析android源目录,需要提取除特定模式之外的所有目录名。如果您注意下面的内容,现在我只在排除列表中包含了一个目录,但我将添加更多 find命令不排除名为“docs”的目录 注释掉的行可以工作,但另一行不行。为了便于调试,我加入了mindepth和maxdepth,稍后将删除它们 有没有关于它为什么不起作用的评论或提示 #! /bin/bash ANDROID_PATH=$1 root=/ EXCLUDES=( doc ) cd ${root} for dir in "${EXCL

我正在尝试解析android源目录,需要提取除特定模式之外的所有目录名。如果您注意下面的内容,现在我只在排除列表中包含了一个目录,但我将添加更多

find命令不排除名为“docs”的目录

注释掉的行可以工作,但另一行不行。为了便于调试,我加入了mindepth和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} 

发现了问题。它与exclude_name_cmd_字符串中的转义序列相同。 应该使用正确的语法

当我以以下方式运行脚本(名为
fin.sh
)时:

跟踪输出的一行是:

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
不太熟悉,所以我不能肯定。

用可能引用的参数构建命令字符串是个坏主意。你会进入嵌套的引用级别和
eval
以及其他一些危险的/令人困惑的语法内容

使用数组构建
查找
;你已经把排除在其中了

而且,重复的
-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展开返回的文件列表,也不是包含文本引号的字符串。如果您试图将命令构建为字符串,则很难做到这一点,但如果您使用数组,则很难做到这一点


Friends不允许Friends将shell命令构建为字符串

@Jonathan Leffler-嗨。。。很抱歉我没有把它清理干净。事实上,有很多未使用的东西,因为我在尝试不同的东西。我会打扫的up@JonathanLeffler-已完成清理:)
find /Users/jleffler/tmp -mindepth 1 -maxdepth 1 -not -name '"doc*"' -prune -type d
excludes=()

for dir in "${EXCLUDES[@]}"; do
  excludes+=(-name "${dir}*" -prune -o) 
done

find "${ANDROID_PATH}" -mindepth 1 -maxdepth 1 "${excludes[@]}" -type d -print