“find:bad option -name”* .user“”在传递变量时查找

时间:2014-09-14 14:10:43

标签: bash find

在bash脚本中,这会失败:

fileloc='/var/adm/logs/morelogs'
filename=' -name "*.user"'

fileList="$(find "$fileloc"/* -type f -prune "$filename" -print)"


find: bad option  -name "*.user"
find: [-H | -L] path-list predicate-list

但这有效:

find /var/adm/logs/morelogs/* -type f -prune -name "*.user" -print

以同样的方式: 这失败了:

fileloc='/var/adm/logs/morelogs'
filename='\( -name "admin.*" -o -name "*.user" -o -name "*.user.gz" \)'

fileList="$(find "$fileloc"/* -type f -prune "$filename" -print)"


find: bad option  \( -name "admin.*" -o -name "*.user" -o -name "*.user.gz" \)
find: [-H | -L] path-list predicate-list

但这有效:

find /var/adm/logs/morelogs/* -type f -prune \( -name "admin.*" -o -name "*.user" -o -name "*.user.gz" \) -print

GNU bash,版本3.00.16(1)-release-(sparc-sun-solaris2.10)

4 个答案:

答案 0 :(得分:3)

当您应该使用BASH数组或BASH函数时,这是用例。

使用BASH数组:

#!/bin/bash

# initialize your constants
fileloc='/var/adm/logs/morelogs'
filename='*.user'

# create an array with full find command
cmd=( find "$fileloc" -type f -prune -name "$filename" -print )

# execute find command line using BASH array
"${cmd[@]}"

答案 1 :(得分:2)

让我们看看你在set -x

做了什么
$ fileloc='/var/adm/logs/morelogs'
+ fileloc=/var/adm/logs/morelogs
$ filename=' -name "*.user"'
+ filename=' -name "*.user"'

一切似乎都很好,现在,下一行:

$ fileList="$(find "$fileloc"/* -type f -prune "$filename" -print)"
++ find '/var/adm/logs/morelogs/*' -type f -prune ' -name "*.user"' -print
find: paths must precede expression:  -name "*.user"
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
+ fileList=

我认为你看到了问题,如果你执行find '/var/adm/logs/morelogs/*' -type f -prune ' -name "*.user"' -print它会给你一个错误:

$ find '/var/adm/logs/morelogs/*' -type f -prune ' -name "*.user"' -print
find: paths must precede expression:  -name "*.user"
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

发生了什么事?好吧,有一堆单引号挡在路上,但导致问题的是两个持续时间,在-name-print之前,这导致find将其视为单个参数,其他可以忽略。那么,如何解决这个问题呢?不要使用双引号来询问$filename变量:

$ find "$fileloc" -type f -prune $filename -print
+ find /var/adm/logs/morelogs -type f -prune -name '*.user' -print

那应该解决它。

答案 2 :(得分:2)

听起来你正在尝试构建要动态搜索的名称列表 - 如果是这种情况,@ anubhava使用数组仅为名称模式的答案的变体是最好的方法:

namepatterns=() # Start with no filenames to search for
while something; do
    newsuffix="whatever"
    namepatterns+=(-o -name "*.$newsuffix")
done

# Note that "${namepatterns[@]}" is not quite what we want to pass to find, since
# it always starts with "-o" (unless it's empty, in which case this'll have other
# problems). But "${namepatterns[@]:1}" leaves off the first element, and gets us
# what we need.
fileList="$(find "$fileloc"/* -type f -prune "(" "${namepatterns[@]:1}" ")" -print)"

其他说明:我的第二个@ BroSlow建议阅读BashFAQ #50: I'm trying to put a command in a variable, but the complex cases always fail!,如果任何文件名包含有趣的字符(尤其是空格和通配符),您将无法使用该文件列表变量 - 请参阅BashFAQ #20: How can I find and safely handle file names containing newlines, spaces or both?(简短回答:阵列也更好!)

答案 3 :(得分:0)

不是问题的答案,而是一个糟糕的解决方案。在感到沮丧之后,我只是将搜索硬编码为具有完整选项列表。

所以它现在看起来像这样:它有效。我不得不建立一些案例,并重复自己 - 不是一个好的编程实践,但我已经厌倦了这个shell ting ....

所以例如一个选项如下:

fileList="$(find "$fileloc"/* -type f -prune \( -name "admin.*" -o -name "*.user" -o -name "*.user.gz" \) -print)"