faceless
faceless

Reputation: 488

find: name pattern as a variable

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

Answers (2)

glenn jackman
glenn jackman

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

ceving
ceving

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

Related Questions