在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)
答案 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)"