How to access literal wildcard argument before it's expanded to matching files?

♀尐吖头ヾ 提交于 2019-12-22 08:22:50

问题


Background:

I'm writing a bash script that must receive these arguments:

  1. a file name (a file containing a set of rules )
  2. a list of file names ( files to be processed, can use wildcards)
  3. a destination folder ( where processed versions of files will be stored )

In theory there are 3 parameters but in reality the second argument expands, so the real number of argument varies if the wildcard matches more than one file:

When I call

./myscript  file.conf *.data dest_foder

*.data expands into as many files match the wildcard so it's equivalent to:

myscript file.conf this.data that.data so.data dest_foder

Prior to processing I need to validate that the last argument is a folder and not a file.

The problem

If I ommit the destination folder, like:

myscript file.conf *.data

The validation ?# -ge 3 passes because the wildcard returns more than one item, and if a folder that matches the wildcard happens to exist, like this_is_a_folder.data, then the expansion is like this:

myscript file.conf this.data that.data so.data this_is_a_folder.data

The script will work but in a non-expected way... it will process this.data, that.data and so.data and put the processed versions of the files in the folder this_is_a_folder.data.

Question

  • How do I avoid that ?
  • How can I validate that the destination folder was explicitly passed as an argument and not the product of the expansion of the wildcard in the second parameter ?

I cannot find a way to read the literal "*.data" argument before it's expanded into matching filenames.

Clarifying:

I know how to read the last argument.

  • But how do I know whether that last argument was explicitly passed or was the product a wild card expansion ?

回答1:


You can't do this, since the shell expands any wildcards in the command line before your script even starts. When you enter ./myscript file.conf *.data dest_foder in the shell, this is effectively just a shorthand for ./myscript file.conf this.data that.data so.data dest_foder, not a different command.

If you need the wildcard passed into the command as an actual argument, you need to quote or escape it. Something like ./myscript file.conf '*.data' dest_foder or ./myscript file.conf \*.data dest_foder. Alternately, make the last argument mandatory, or turn it into an option (-d dest_folder) so the preexpanded file list isn't a problem.

Put it another way: it'd be very convenient if you didn't have to quote/escape wildcards in your grep patterns; but you have to, because there's no way for the grep command to get at its arguments in unexpanded form. And if the authors of grep couldn't figure out how to make their command more convenient, there's no way you're going to be able to do it...




回答2:


Your script can not know, since it is passed the arguments by the shell, and it will have no notion of the state of the calling process. Why not

  1. Reorder your arguments so that the variable length arguments come last
  2. Use commandline flags such as --dest/-d DEST_DIR

This would be more consistent with UNIX tool conventions.



来源:https://stackoverflow.com/questions/18060389/how-to-access-literal-wildcard-argument-before-its-expanded-to-matching-files

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!