以编程方式构建目录排除列表以查找命令(重击) [英] Build Directory Exclusion List Programmatically for Find Command (Bash)
问题描述
我有一个目录数组要从我的find命令的结果中排除,例如EXCLUDE=("foo" "bar")
.
我可以像这样从交互式终端运行它:
find . -name 'hvr.yml' -not -path "foo/*" -not -path "bar/*"
所以我试图像这样建立论点:
getServersToCheck() {
# Build command arguments to exclude given dirs
local exclude_command="-not -path"
local excount=${#EXCLUDE[@]}
for ((i=0;i<excount;i++)); do
EXCLUDE[i]="${exclude_command} ${EXCLUDE[i]}/*"
done
find . -name 'hvr.yml' "${EXCLUDE[@]}"
}
但这会导致find抛出未知的谓词错误:'-not -path foo/*'
有没有办法做到这一点?当我回显该命令时,它看起来是正确的,但是必须有一些bash语法规则导致该命令无法按我期望的那样工作.
更新:
我在路径周围添加了\"
以排除,因为我读到globation仅发生在带引号的字符串中. xtrace显示以下内容:
find . -name hvr.yml -not -path '"foo/*"' -not -path '"bar/*"'
单引号可能是问题
删除\"
并使用xtrace运行表明,该globbing正在for循环中应用,导致:
find . -name hvr.yml -not -path "foo/fileinfoo" "foo/somethingelseinfoo" -not -path "bar/*" "bar/fileinbar" "bar/otherfilesinbar"
所以find抱怨把随机路径作为参数给出.
是否可以扩展EXCLUDE数组并将/*添加到命令中每个元素的末尾?
找到了我尝试使用grep实现的替代解决方案:
EXCLUDE=("abc" "def")
getPaths() {
local exclude_count=${#EXCLUDE[@]}
if [ $exclude_count -eq 0 ]; then
find . -name $FILENAME | tr '\n' ' '
return $?
fi
# Concat excluded servers as grep regex
local regex="(${EXCLUDE[0]}"
for ((i=1;i<exclude_count;i++)); do
regex="${regex}|${EXCLUDE[i]}"
done
regex="${regex})"
find . -name $FILENAME | grep -Ev "${regex}" | tr '\n' ' '
return $?
}
- 如果exclude为空,则运行常规的find命令.
- 否则,它会为grep建立一个正则表达式,以过滤掉最终看起来像(abc | def)的示例.
I have an array of directories to exlude from the result of my find command, something like EXCLUDE=("foo" "bar")
.
I can run this from the interactive terminal like so:
find . -name 'hvr.yml' -not -path "foo/*" -not -path "bar/*"
And so i tried to build the argument up like this:
getServersToCheck() {
# Build command arguments to exclude given dirs
local exclude_command="-not -path"
local excount=${#EXCLUDE[@]}
for ((i=0;i<excount;i++)); do
EXCLUDE[i]="${exclude_command} ${EXCLUDE[i]}/*"
done
find . -name 'hvr.yml' "${EXCLUDE[@]}"
}
But this results in find throwing an unknown predicate error: '-not -path foo/*'
Is there way of achieving this? When I echo the command it looks correct, but there must be some bash syntax rules that are causing this not to work how I expect.
UPDATE:
I added \"
around the path to exclude as I read that globbing only occurs with quoted strings. xtrace shows this following:
find . -name hvr.yml -not -path '"foo/*"' -not -path '"bar/*"'
The single quotes possibly being the problem
Removing the \"
and running with xtrace shows that the globbing is being applied in the for loop, resulting in:
find . -name hvr.yml -not -path "foo/fileinfoo" "foo/somethingelseinfoo" -not -path "bar/*" "bar/fileinbar" "bar/otherfilesinbar"
And so find is complaining about random paths being given as arguments.
Is there way to expand the EXCLUDE array and add /* to the end of each element in the command?
Found an alternative solution to what I was trying to achieve by using grep:
EXCLUDE=("abc" "def")
getPaths() {
local exclude_count=${#EXCLUDE[@]}
if [ $exclude_count -eq 0 ]; then
find . -name $FILENAME | tr '\n' ' '
return $?
fi
# Concat excluded servers as grep regex
local regex="(${EXCLUDE[0]}"
for ((i=1;i<exclude_count;i++)); do
regex="${regex}|${EXCLUDE[i]}"
done
regex="${regex})"
find . -name $FILENAME | grep -Ev "${regex}" | tr '\n' ' '
return $?
}
- If exclude is empty, this runs a normal find command.
- Otherwise, it builds up a regex for grep to filter out that ends up looking like (abc|def) for this example.
这篇关于以编程方式构建目录排除列表以查找命令(重击)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!