Reputation: 488
A trivial situation where I want to manage the file name patterns for the find
command in the variable:
/bin/bash
EXCLUDE="! \( -name "\"run*"\" -o -name "\"doc*"\" \)"
find . -maxdepth 1 -type f "$EXCLUDE"
The expectation is to find all the files not matching the $EXCLUDE
pattern.
The approach doesn't work, despite the same pattern directly works as expected.
In the shell tracing mode I observed something that I blame as a potential rootcause - the $EXCLUDE
variable is evaluated between single quotes:
set -x
find . -maxdepth 1 -type f "$EXCLUDE"
+ find . -maxdepth 1 -type f '! \( -name "run*" -o -name "doc*" \)'
find: paths must precede expression: ! \( -name "run*" -o -name "doc*" \)
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
The substituted $EXCLUDE
variable appears in the line starting with +
and my find
command won't return anything with those characters: '! \( -name "run*" -o -name "doc*" \)'
.
Is there a way to remove those quotes, which are not a part of the variable, or I am missing something bigger?
Upvotes: 1
Views: 806
Reputation: 246744
This is BashFAQ/050 -- use an array instead:
EXCLUDE=( '!' '(' -name 'run*' -o -name 'doc*' ')' )
Then use the array expansion syntax
find . -maxdepth 1 -type f "${EXCLUDE[@]}"
Upvotes: 2
Reputation: 23794
Store the arguments in an array:
#! /bin/bash
EXCLUDE=( '!' '(' '-name' 'run*' '-o' '-name' 'doc*' ')' )
find . -maxdepth 1 -type f "${EXCLUDE[@]}"
This avoids quoting errors.
Upvotes: 2