1

Let see the following code:

#!/bin/bash
arg=$1
echo $arg

If I run it with argument it prints the argument; if not it does nothing. What I want to know, is it possible to find out if it takes a command line argument or not before or without running it?

  • You can run a search for $1 in the script. Or if the person wrote it well it should have a -h --help or should just print usage information if ran without required arguments. Most of my scripts that require arguments have the following: if [[ -z $1 ]]; then echo -e "Usage: Script ..."; – Jesse_b Aug 14 '17 at 14:53
  • 2
    I wouldn't count on the presence of $1 -- I might use if [[ $# -gt 0 ]] or for arg in "$@"; do or even for arg; do – glenn jackman Aug 14 '17 at 15:27
  • I wasn't even really familiar with $@ I just figured there is probably no way to even have $2 without having a $1 but good point. – Jesse_b Aug 14 '17 at 15:30
  • Reading the script and/or its documentation (incl. comments) is the only way to be sure, but @Kusalananda's answer below is a good way to find those that might take args (a short list to examine directly). – cas Aug 14 '17 at 16:07
5

sh-compatible shell scripts that uses the arguments on the command line will often contain either $1, $2, $3 etc. or $@ or $* or combinations thereof. However, this is neither necessary nor sufficient!

This greps the script and returns all lines that contains these kinds of strings:

grep '\$[1-9@*]' script.sh

You may get false positives from scripts that don't take command line arguments but that contain functions that takes arguments, or scripts that simply contains these characters in unevaluated strings. If the script contains calls to awk for example, then these may also contain $1 etc. that does not refer to the command line arguments of the script itself.

You may also look for the string getopt in the script to see whether the script uses getopt or getopts to do proper parsing of the command line.

Catching the cases where the command line arguments may be used implicitly is a bit harder. This happens, for example, with for variablename; do ... done or select variablename; do ... done. But if the script has used set to populate the positional parameters explicitly, then this doesn't touch any command line arguments. Visual inspection of the script may be needed to sort this out.

In "real life", one would read the accompanying documentation. If for whatever strange reason that's not available, then read the code.

  • You might use the pattern \${\?[1-9@*#] -- in case the script uses ${1} form. Also, a script may use the for arg; do to iterate over the positional parameters without every referring to them by name. The only reliable answer is to read the code. – glenn jackman Aug 14 '17 at 15:30
  • I personnally use a lot : ${n} instead of $n, so : grep '\${*[1-9@*]}*' (but there can be many other variations : ${n:-default}, etc) – Olivier Dulac Aug 14 '17 at 15:31
  • 1
    also, some scripts never use "$1" etc directly but use getopts or getopt instead. so: grep -E '\$[1-9@*]|getopt' script.sh. NOTE that some scripts don't take arguments but populate $1, $2, etc with set -- for convenient use with $@ (not uncommon with sh-like shells that don't support array variables). and some don't use args or getopt/getopts themselves but have function definitions that take args, or use getopt/getopts. – cas Aug 14 '17 at 15:58
  • 1
    Positional parameters can be accessed via for var; do ..., too. – Hauke Laging Aug 14 '17 at 18:25
  • Additionally the script may source other files. In this case they should be inspected as well. – Kamil Maciorowski Aug 15 '17 at 22:17
3

You can't. This question is in general undecidable - no matter what algorithm you invent, one can come up with an example where it would fail. Just to wet your appetite, consider the following scripts - do they take an argument or not?

# script 1
false && echo catch $1 if you can

# script 2
x='$'
y=1
eval echo $x$y
0

The requirement is not meaningful. A program receives a list of command line arguments and chooses what it does with it. A shell script or any other program takes as many command line arguments as it wants.

You could define “takes command line arguments” as “doesn't do anything useful when called with 0 arguments”. But then you'd need to define “useful”. The example script you give does something when called with no arguments: it prints a blank line. Why do you define printing a blank line as not useful?

Another possible definition is that a program “takes command line arguments” if it behaves differently when passed at least one command line argument than with 0. This is the most natural definition for me, but evidently that isn't the definition you're using since your example script does use its first argument to determine what to output.

You need to rethink your problem. What do you mean by “takes command line arguments”? Once you've defined your problem, you'll be closer to a solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.