首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在bash中构造变长参数行到外部命令的正确方法

问在bash中构造变长参数行到外部命令的正确方法
EN

Unix & Linux用户
提问于 2018-05-16 08:33:43
回答 2查看 691关注 0票数 1

我需要使用“查找”命令在我的Bash函数中查找几组不同的文件,这取决于我的脚本输入。

所以,我有一件事:

代码语言:javascript
复制
DAYS=30
case $1 in
A1) ARGLINE="-name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt'"
    ;;
A2) ARGLINE="-name 'PO*xml' -or -name 'PR*xml'"
    ;;
...
esac
find . -maxdepth 1 -type f -mtime +${DAYS} `${ARGLINE}`

This工作。

但是,只要我想使用变量来搜索返回的天数,如下所示:

代码语言:javascript
复制
DAYS=30
case $1 in
A1) ARGLINE="-name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt'"
    ;;
A2) ARGLINE="-name 'PO*xml' -or -name 'PR*xml'"
    ;;
...
esac
if [[ $# -gt 1 ]]; then
    DAYS=$2
fi
find . -maxdepth 1 -type f -mtime +${DAYS} `${ARGLINE}`

当find找不到与其匹配的任何文件时,该函数将失败,并出现以下错误:

您的意思是:命令'uname‘来自包'coreutils’(主) -name:命令未找到

但是,当找到一些文件的天数达到一定程度时,它就可以正常工作了。当我试图将连续运行的输出输送到另一个命令时,它也会失败。

如何正确构建“查找”的参数行?

EN

回答 2

Unix & Linux用户

回答已采纳

发布于 2018-05-16 08:37:37

在bash中,使用一个数组:

代码语言:javascript
复制
args=( '(' -name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt' ')' )

额外的括号用于创建正确的布尔逻辑分组,因为您使用了-or)。

然后,在find命令中:

代码语言:javascript
复制
find ...some arguments... "${args[@]}"

您有一个额外的问题,您使用

代码语言:javascript
复制
`$ARGLINE`

这是一个类似于$( $ARGLINE )的命令替换,shell将尝试将$ARGLINE (其值)作为命令执行。这就是为什么你得到“没有命令‘-名字’找到”。命令替换失败,但find运行,这就是您认为它“工作”的原因。

票数 5
EN

Unix & Linux用户

发布于 2018-05-16 08:38:59

这里的主要问题是引号在引号中不起作用:在展开变量之后,其中的引号只是普通字符,例如:

代码语言:javascript
复制
$ foo='foo "bar doo"'
$ printf "<%s>\n" $foo

<"bar>

您应该使用数组来存储这样的命令参数:

代码语言:javascript
复制
ARGS=(-name 'FOO*.xml' -or -name 'BAR*.xml' -or -name 'BTT*.txt')

shell将在此阶段处理引用,并将不同的shell单词存储为不同的数组元素。使用这样的数组:

代码语言:javascript
复制
find . "${ARGLINE[@]}"

如果您想要或需要,可以逐片构建数组,这应该会产生相同的数组:

代码语言:javascript
复制
ARGS=(-name 'FOO*.xml')
ARGS+=(-or -name 'BAR*.xml')
ARGS+=(-or -name 'BTT*.txt')

但是,请注意,您还使用了backticks来“引用”${ARGLINE}。它将启动命令替换,并以命令的形式运行ARGLINE的内容。这就是您的错误来源,shell试图运行一个名为-name的程序。

实际上,在您的示例中,您不需要数组,因为参数中没有任何空格。这里的主要问题通常是,当命令行存储到一个字符串时,参数之间的空格和参数中的空白之间的区别就会丢失。但在你的例子中,这可能是可行的,不是我推荐的:

代码语言:javascript
复制
set -f       # disable globbing
ARGLINE="-name FOO*.xml -or -name BAR*.xml -or -name BTT*.txt"
find . $ARGLINE
票数 3
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/444113

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档