背景:
我正在编写一个必须接收这些参数的 bash 脚本:
- 一个文件名(包含一组规则的文件)
- 文件名列表(待处理的文件,可以使用通配符)
- 目标文件夹(将存储经过处理的文件版本)
理论上有 3 个参数,但实际上第二个参数会扩展,因此如果通配符匹配多个文件,参数的实际数量会有所不同:
当我打电话
./myscript file.conf *.data dest_foder
*.data
扩展成与通配符匹配的文件,因此它等同于:
myscript file.conf this.data that.data so.data dest_foder
在处理之前,我需要验证最后一个参数是文件夹而不是文件。
问题
如果我省略目标文件夹,例如:
myscript file.conf *.data
验证 ?# -ge 3
通过是因为通配符返回了不止一项,并且如果恰好存在与通配符匹配的文件夹,如 this_is_a_folder.data
,那么展开是这样的:
myscript file.conf this.data that.data so.data this_is_a_folder.data
该脚本将以一种非预期的方式运行...它将处理 this.data、that.data 和 so.data
并将文件的处理版本放入文件夹 this_is_a_folder.data
。
问题
- 如何避免这种情况?
- 如何验证目标文件夹是作为参数显式传递的,而不是第二个参数中通配符扩展的产物?
在扩展为匹配的文件名之前,我找不到读取文字“*.data”参数的方法。
澄清:
我知道如何阅读最后一个参数。
- 但是我怎么知道最后一个参数是否被明确传递或者产品是通配符扩展?
最佳答案
您不能这样做,因为 shell 甚至在您的脚本启动之前就已在命令行中扩展了所有通配符。当您在 shell 中输入 ./myscript file.conf *.data dest_foder
时,这实际上只是 ./myscript file.conf this.data that.data so.data dest_foder 的简写
,不是不同的命令。
如果您需要将通配符作为实际参数传递给命令,则需要将其引用或转义。类似于 ./myscript file.conf '*.data' dest_foder
或 ./myscript file.conf\*.data dest_foder
。或者,使最后一个参数成为必需参数,或将其变成一个选项 (-d dest_folder
),这样预扩展的文件列表就不是问题了。
换句话说:如果您不必在 grep 模式中引用/转义通配符,那将非常方便;但是您必须这样做,因为 grep
命令无法以未展开的形式获取其参数。如果 grep
的作者无法弄清楚如何使他们的命令更方便,那么您将无法做到...
关于bash - 如何在扩展为匹配文件之前访问文字通配符参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18060389/