linux find添加变量,linux - find命令在提示符下起作用,而不是在bash脚本中起作用-通过变量传递多个参数 - 堆栈内存溢出...

注意:正如Etan在评论中指出的那样,在这种情况下,更好的解决方案可能是重新编写find命令,但是一般通过变量传递多个参数是一种值得探索的技术。

tl; dr :

问题不是特定于find ,而是Shell如何解析命令行的问题 。

嵌入在变量值中的引号字符被视为文字 :它们既不被识别为参数边界定界符,也不在解析后将其删除 ,因此, 不能将嵌入引号的字符串变量与 直接用作参数的一部分的传递给多个参数一起 使用命令 。

为了可靠地传递存储在变量中的多个参数 ,

在支持它们的shell中使用数组变量 ( bash , ksh , zsh )-参见下文。

否则, 为了符合POSIX,请使用xargs参见下文。

强大的解决方案 :

注意:这些解决方案假定存在以下脚本 ,我们称其为echoArgs ,该脚本以诊断形式打印传递给它的参数:

#!/usr/bin/env bash

for arg; do # loop over all arguments

echo "[$arg]" # print each argument enclosed in [] so as to see its boundaries

done

此外,假定将执行以下命令的等效项 :

echoArgs one 'two three' '*' last # note the *literal* '*' - no globbing

除了最后一个 变量以外的所有参数 。

因此,预期结果是:

[one]

[two three]

[*]

[last]

使用数组变量( bash , ksh , zsh ):

# Assign the arguments to *individual elements* of *array* args.

# The resulting array looks like this: [0]="one" [1]="two three" [2]="*"

args=( one 'two three' '*' )

# Safely pass these arguments - note the need to *double-quote* the array reference:

echoArgs "${args[@]}" last

使用xargs 兼容POSIX的替代方法:

POSIX实用xargs ,不像外壳本身, 能够嵌入在一个字符串认可引号字符串:

# Store the arguments as *single string* with *embedded quoting*.

args="one 'two three' '*'"

# Let *xargs* parse the embedded quoted strings correctly.

# Note the need to double-quote $args.

echo "$args" | xargs -J {} echoArgs {} last

请注意, {}是一个自由选择的占位符,它允许您控制xargs提供的参数在结果命令行中的位置。

如果所有xarg参数都xarg在最后 ,则根本不需要使用-J 。

为了完整起见: eval也可以用于解析嵌入在另一个字符串中的带引号的字符串,但是eval存在安全风险:任意命令最终可能会被执行; 鉴于以上讨论的安全解决方案,因此无需使用eval 。

最后,查尔斯·达菲(Charles Duffy)在注释中提到了另一种安全的替代方法,但是,它需要更多的编码:将要调用的命令封装在shell函数中 ,将变量参数作为单独的参数传递给该函数,然后操纵所有参数数组$@在函数内部以补充固定参数(使用set ),并使用"$@"调用命令。

有关shell的字符串处理问题的说明:

将字符串分配给变量时 , 嵌入的引号字符将成为字符串的一部分 :var='one "two three" *'

$var现在从字面上包含one "two three" * ,即以下4个单词(而不是预期的3个单词),每个单词之间用空格分隔:

one

"two - "是单词本身的一部分!

three" - "是单词本身的一部分!

*

当您使用$var 引号作为参数列表的一部分时, 上述分解成4个单词的过程正是Shell 最初要做的事情 -这个过程称为单词拆分 。 请注意,如果要对变量引用( "$var" ) 双引号 ,则整个字符串将始终成为单个参数。

由于$var被扩展为其值,即所谓的参数扩展之一 , 因此外壳程序不会尝试将该值内的嵌入引号识别为标记参数边界 -这仅适用于按字面指定的引号字符,这是该变量的直接部分。命令行(假设这些引号字符本身没有被引号)。

类似地,在将封闭的字符串传递给被调用的命令之前,shell只会删除这些直接指定的引号字符-这个过程称为quote remove 。

但是,shell 还会对结果的4个单词应用路径名扩展 (globbing),因此,碰巧与文件名匹配的任何单词都将扩展为匹配的文件名。

简而言之: $var值中的引号字符既不识别为参数边界定界符,也不在解析后将其删除 。 此外, $var值中的单词会受到路径名扩展的影响 。

这意味着传递多个参数的唯一方法是在变量值内不加引号 (并且对变量的引用也不要加引号 ),这是:

不适用于带有嵌入式空格或外壳元字符的值

始终使值经受路径名扩展

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值