【问题标题】:trouble with bash script setting up params for 'find' utilitybash 脚本为“查找”实用程序设置参数时遇到问题
【发布时间】:2011-12-16 01:48:42
【问题描述】:

这里的基本问题是我想使用脚本来简化“查找”实用程序跳过某个麻烦的目录。

Bash 脚本不是我的强项。我被困在如何将命令行上带引号的通配符文件规范放入脚本中,然后从那里毫发无损地进入 find 命令。似乎 bash 喜欢去掉引号并将包含通配符的单词扩展为单词列表,这通常很好,但是当我尝试在脚本中评估“find”时,这个命令行烹饪会发生两次,结果不理想。

现在我要给出血淋淋的细节,b/c 也许有人会看到我真正想要做的事情并说“嘿,你知道有一个更简单的方法可以做到这一点”。解决这个问题对我来说很好。

所以,背景-

在有问题的机器上,有一个自动备份系统,可以归档大约两打某些目录的快照,例如用户的主目录和各种项目位置。所以在我的主目录中,我有 ~/.backup/hourly.0、~/.backup/hourly.1 等到大约 hourly.12,然后是 nightly.1 到大约 nightly.12,所以有大量的重复。通常这是一个很好的安全网,直到我想在我的主目录中“找到”一些东西。

例如,假设我要查找所有 *.foo 文件;简单的解决方案是发布

find ~ -name "*.foo"

.. 除了在这台机器上,find 开始筛选所有这些备份目录。通常我对 .backup 目录中的点击不感兴趣。搜索它们很慢,而且据我所知,它们是安装在网络上的,而且我正在融化某人的数据柜。所以下一个演变是用这样的形式做一些事情

find ~ ! \( -name .backup -prune \) -a -name "*.foo"

.. 有效,如果只需要使用一次或两次,还不错。但是它很容易胖手指,并且当连续需要几次时会很烦人。所以编写一个脚本来处理这个似乎是个好主意。由于缺乏更具想象力的名称,让我们使用“findx”。想法是发出 findx ~ -name "*.foo",并让 'findx' 自动将其转换为更复杂的形式。脚本的第一个 hack 看起来像这样

find $1 ! \( -name .backup -prune \) $2 $3 $4 $5 $6 $7

诚然,这看起来非常笨拙,并且不适用于具有太多参数的搜索。 (如果有办法指定“从第二个参数开始的所有参数”,我不知道。) find 命令的特殊语法似乎要求将 $1 与其余参数分开,b/c 搜索根location 必须先出现,如果 -prune 和 -print 子句以相反的顺序排列,则它们将无法正常工作,因此 -prune 必须位于(隐式)打印的内容之前,在右侧留下 $2 $3 等。无论如何,对于足够简单的搜索应该已经足够了。

嗯,这对于特定的文件名似乎可以正常工作,但是通配符会导致它失败。似乎,例如,我喂它

findx . -name "*stuff"

那个 bash first 在将 *stuff 作为 $ 参数之一传递到脚本之前,将引号从 *stuff 中去除。然后构建的 find 命令没有引号包裹通配符;因此,当 that 被执行时,shell 在执行 find 之前扩展 *,然后阻塞,b/c find 想要一个单词 *stuff 而不是它扩展的列表。 (显然 find 喜欢做自己的通配符扩展?)

那么 - 有没有办法让这个工作?有没有其他方法可以省略搜索一个不是那么冗长的目录,从而消除脚本的动机? find 的替代方法,它可以完成大多数 find 可以做的事情,例如 -ctime、-type、-name 等等?

【问题讨论】:

    标签: bash find wildcard


    【解决方案1】:

    如果有办法指定'从第二个开始的所有参数',我不知道。

    是"${@:2}",如:

    find "$1" ! \( -name .backup -prune \) "${@:2}"
    

    The Bash Reference Manual 读起来有点密集,但它确实描述了这种行为,如果你知道在哪里看的话。具体来说,在§3.5.3 Shell Parameter Expansion中,${parameter:offset}和${parameter:offset:length}的描述中提到“如果参数是'@',结果是length em> 位置参数从 offset 开始”,然后是“子字符串索引是从零开始的,除非使用位置参数,在这种情况下,索引默认从 1 开始。”

    【讨论】:

    • 另外,请注意,双引号中的参数引用应该解决通配符错误行为(并处理空格和参数,以及......),据我所知,这应该完全解决这两个问题问题。
    【解决方案2】:

    不是一个完整的答案,但是看着 thd ABS Guide,我看到了一些有趣的事情。

    $@

    与$*相同,但每个参数都是一个带引号的字符串,即参数原封不动地传递,没有解释或扩展。这意味着,除其他外,参数列表中的每个参数都被视为一个单独的词。

    这对通配符扩展问题很有用。

    换档后,$@ 保存剩余的命令行参数,缺少之前丢失的 $1。

    这与指定从第二个开始的所有参数的方式。

    我希望这会有所帮助。

    【讨论】:

    • 好的,听起来很诱人,但有一个问题 - 什么是“转变”?我想应该有一种方法可以一次拉出一个参数,并有一种方法可以引用剩下的东西,这听起来像这样。只是不知道从列表中删除第一个的机制是什么。
    • 您可以在Bash Guide 中找到有关shift 的信息。
    • 万一以后有人来这里,我会很容易的。 'shift' 只是一个命令。如果你说'shift 1',那么所有的论点都会滑到一个位置;以前 2 美元的价值现在是 1 美元,等等。
    猜你喜欢
    • 2019-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 2011-10-15
    相关资源
    最近更新 更多