I'm trying to write a script where I want to check if any of the parameters passed to a bash script match a string. The way I have it setup right now is

if [ "$3" != "-disCopperBld" -a "$4" != "-disCopperBld" -a "$5" != "-disCopperBld" -a "$6" != "-disCopperBld"]

but there might be a large number of parameters, so I was wondering if there is a better way to do this?


EDIT: I tried this chunk of code out, and called the script with the option, -disableVenusBld, but it still prints out "Starting build". Am I doing something wrong? Thanks in advance!

while [ $# -ne 0 ]
    case "$arg" in

if [ "$disableVenusBld" != true ]; then
    echo "Starting build"
  • Thanks for the replies guys, I appreciate ya'll taking time out to help me. I tried a chunk of code, but I can't seem to figure out what's going wrong. Any ideas? (I've pasted the code in an edit of my original post)
    – iman453
    Sep 9 '10 at 15:29
  • Hmm: it works for me. I added #! /bin/sh - to the top of what you've included there, made the script executable, then ./t.sh prints "Starting build", but ./t.sh -disableVenusBld prints nothing. Sep 9 '10 at 21:47
  • for a in "$@"; do [[ "$a" == "-disCopperBld" ]] && echo match; done
    – bvj
    Sep 19 '20 at 0:50

It looks like you're doing option handling in a shell script. Here's the idiom for that:

#! /bin/sh -

# idiomatic parameter and option handling in sh
while test $# -gt 0
    case "$1" in
        --opt1) echo "option 1"
        --opt2) echo "option 2"
        --*) echo "bad option $1"
        *) echo "argument $1"

exit 0

(There are a couple of conventions for indenting the ;;, and some shells allow you to give the options as (--opt1), to help with brace matching, but this is the basic idea)

  • 4
    A shift statement is used when the number of arguments to a command is not known in advance, for instance when users can give as many arguments as they like. In such cases, the arguments are processed in a while loop with a test condition of $#. This condition is true as long as the number of arguments is greater than zero. The $1 variable and the shift statement process each argument. The number of arguments is reduced each time shift is executed and eventually becomes zero, upon which the while loop exits. source Jan 22 '15 at 22:47
  • Here is a similar example with additional echo $1 | sed argument value processing. Jan 22 '15 at 22:57

This worked for me. It does exactly what you asked and nothing more (no option processing). Whether that's good or bad is an exercise for the poster :)

if [[ "$*" == *YOURSTRING* ]]
    echo "YES"
    echo "NO"

This takes advantage of special handling of $* and bash super-test [[]] brackets.

  • 2
    IMHO this had to be the most correct answer, since the question requires only to check the presence of a parameter. I have edited, however, changing $* to $@, since the to-be-tested string might have spaces and added link to bash's documentation about it.
    – h7r
    Feb 1 '15 at 12:51
  • 9
    Did you mean to use the =~ operator? Otherwise I don't see why this should work, and indeed it doesn't work when I try the exact script. Jul 14 '15 at 8:37
  • 3
    Not working. bash -c 'echo args=$*; [[ "$@" == "bar" ]] && echo YES || echo NO' -- foo bar
    – Tobia
    Nov 4 '15 at 11:55
  • 6
    This answer has been wrong for the past four years because h7r’s edit broke it.  The original answer (which I have now restored) works, provided “your string” contains no glob characters, and with some false positives.  For example, if the command is create a new certificate and “your string” is cat, this will report a match because certificate contains cat.
    – Scott
    May 22 '19 at 19:46
  • 8
    Note for noobs like me: the YOURSTRING might be quoted, but the asterisks must be OUTSIDE the quotes, e.g. if [[ "$*" == *"my search string"* ]]
    – velis
    Jun 28 '19 at 7:20

How about searching (with wildcards) the whole parameter space:

if [[ $@ == *'-disableVenusBld'* ]]

Edit: Ok, ok, so that wasn't a popular answer. How about this one, it's perfect!:

if [[ "${@#-disableVenusBld}" = "$@" ]]
    echo "Did not find disableVenusBld"
    echo "Found disableVenusBld"

Edit2: Ok, ok, maybe this isn't perfect... Think it works only if -param is at the start of the list and will also match -paramXZY or -paramABC. I still think the original problem can be solved very nicely with bash string manipulation, but I haven't quite cracked it here... -Can you??

  • Your second suggestion — comparing the filtering substitution to the full substitution — works reasonably well, and has the advantage of not disrupting the list of arguments. May 30 '17 at 13:46
  • Could you explain what the second suggestion (especially ${@#) does?
    – velop
    Nov 14 '17 at 16:01
  • 1
    @velop Sure! So you know that $@ is a special variable that holds all of the command line arguments? Well I've just used Bash string manipulation on that variable to remove the substring "-disableVenusBld", and then I compare it to the original $@. So if $@ equals -foo -bar then ${@#-disableVenusBld} would still be -foo -bar, so I can see that the flag I'm looking for isn't present. However, if $@ equals -foo -disableVenusBld -bar then ${@#-disableVenusBld} would be -foo -bar which is not equal to $@, thus telling me that the flag I'm looking for is present! Cool eh!
    – Rich
    Nov 14 '17 at 20:23
  • @velop Learn more about Bash string manipulation here: tldp.org/LDP/abs/html/string-manipulation.html
    – Rich
    Nov 14 '17 at 20:29
  • @Rich pretty neat ^^, thx for the explanation.
    – velop
    Nov 17 '17 at 10:21
for x; do
  if [ "$x" = "-disCopperBld" ]; then disCopperBld=1; break; fi
if [ -n "$disCopperBld" ]; then

If you need to test only the parameters starting at $3, do the search in a function:

## Usage: search_trailing_parameters NEEDLE NUM "$@"
## Search NEEDLE amongst the parameters, skipping $1 through ${$NUM}.
search_trailing_parameters () {
  shift $(($2 + 2))
  for x; do
    if [ "$x" = "$needle" ]; then return 0; fi
  return 1
if search_trailing_parameters -disCopperBld 2 "$@"; then

But I wonder why you're trying to do this in the first place, it's not a common need. Usually, you'd process options in order, as in Dennis's answer to your previous question.

[[ "$@" =~ '-disableVenusBld' ]] && disableVenusBld=true
[[ "$@" =~ '-disCopperBld' ]] && disCopperBld=true
[[ "$@" =~ '-disableTest' ]] && disableTest=true
[[ "$@" =~ '-disableUpdate' ]] && disableUpdate=true

or more generally

[[ "$@" =~ 'your-string' ]] && ( doSomething )

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.