如何通过带有嵌入式通配符的文件名来查找而不限制本地找到的文件?

问题描述:

我有一个脚本,它使用find来查找与用户输入相匹配的文件。基本上,用户输入类似test*的东西,它应该找到所有匹配的文件。如何通过带有嵌入式通配符的文件名来查找而不限制本地找到的文件?

我遇到的问题是,如果当前目录中有一个文件与用户输入的文件名模式匹配,它只会查找该文件。也就是说,如果用户输入fred*,并且当前目录中有一个名为frederica的文件,该脚本只能找到名为frederica的文件。这里的问题的一个例子:

>ls 
test1 test2 test3 test4 test5 words 
>tmp() 
> { 
> my_file="$1" 
> find . -iname "$my_file" 
> } 
>tmp test* 
./test1 
> 

如果我进入tmp test*,我希望它通过TEST5返回五个文件TEST1。相反,它只返回第一个。此外,如果我搜索了/,它仍然只会从每个目录返回名为test1的文件。

当然,实际的脚本更复杂,我已经开发了一个解决方法,涉及到“通配符选项”(例如,-w 1意味着前导和尾随星号等),但我真的很想能够让用户使用通配符输入文件名。

在此先感谢

+0

为什么不试试''my_file''或者甚至只是'$ my_file' –

+0

这似乎没有帮助 - 在find命令中放置'$ my_file'的单引号会导致找不到任何内容没有引号给出与双引号相同的结果。 –

+0

这与[停止shell通配符扩展?](http://stackoverflow.com/questions/11456403/stop-shell-wildcard-character-expansion)非常紧密相关。 –

当你调用你的函数,你做的方式,即解释呼叫的外壳试图找到匹配的文件(这是进入该功能之前完成),以及不同的事情都可能发生:

  • 如果该glob失败并且设置了shell选项,那么该函数根本就不会被执行。你可能没有看到这个,因为默认的shell选项。

  • 否则,如果glob失败并且nullglob shell选项被设置,那么glob的结果什么也没有,并且没有参数会被传递给你的函数。你可能没有经历过这种事情。

  • 否则,如果glob失败并且未设置failglob shell选项,那么glob的结果就是glob表达式的结果,并将其用作参数值。然后,这个glob表达式被传递到find,并且find做你想做的事情,因为它在内部实现了globbing。你很幸运,但它的工作原理。

  • glob成功并生成一个用作函数参数列表的文件列表。你的电话find使用$1,所以只有这些参数中的第一个被考虑在内,导致你不想要的结果。

双引号或单引号禁用通配符。如果从脚本中使用,你可以因此做:

tmp "test*" 

如果你想在命令行中使用这个命令,你唯一的选择是完全禁止通配,用set -f,这很可能会存在缺陷。

+0

您的描述符合我的经验。我认为failglob没有设置,所以当本地没有匹配的文件时,parm会按原样传递(使用通配符),并且它按照原样运行。 –

+0

不幸的是,禁用globbing不是一种选择,所以它听起来像我坚持我所拥有的 - 依靠一个选项让脚本在内部设置通配符。谢谢! –

+2

@RogerSinasohn在任何情况下,它都能正常工作,因为“它应该”取决于外壳规格,而不取决于你想要的或期望的内容...... – Fred

test*扩展到test1 test2 test3 test4 test5。你只看到$1,即test1

尝试将它称为tmp 'test*'

+0

这很有效,但它意味着训练用户将参数放入单引号内,我认为这些引号不会起作用。但是我认为你可能正在做的事情是 - 在脚本启动之前脚本中(在分配给_my_file_时)或实际命令中发生了'test *'的扩展?也就是说,键入'tmp test *'与输入'tmp test1 test1 test3 test4 test5'实际上是一样的,所以脚本甚至不会看到通配符?这是一个壳问题? –

+0

是的,如果你想传递一个文字'*'来发现你必须从shell引用它。 –

+1

@RogerSinasohn,直接回答你的问题:glob在脚本启动之前被扩展*。该脚本传递一个带有单个字符串列表的参数向量,每个文件一个,并且无法知道原始命令行是什么。 –