[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Why wouldn't "stringing" of an input parameter using an array work? ...



On Sun, Jun 18, 2023 at 11:41:12PM -0500, Albretch Mueller wrote:
> time ( find "${_DIR_BRNX}" -path "${_X_SUB_DIRS_AR[@]}" -prune -type f
> -printf '%s|%d|%P|' -exec file --brief {} \; 1> "${_TMPFL}" 2>
> "${_ERR_LOG}" ) > "${_TM_LOG}" 2>&1

I believe I've said this before, but it DEMANDS repeating: STOP using
these variable names!!

A shell variable that is not being exported through the environment for
another program to use should contain at least one lower-case letter.
It should also not begin with an underscore unless you have a REALLY
GOOD REASON to start it with an underscore.

There are REASONS for these conventions.

The capital letter thing: variables that contain only capital letters,
underscores and digits are part of a namespace that's reserved for
environment variables, and special shell variables.  Examples are
HOME, PATH, RANDOM, BASH_VERSION.

The underscore thing: using a leading underscore is reserved for special
needs.  It's sort of like creating your own semi-private namespace,
except that you're only relying on a gentlemen's agreement to enforce
it.  The one place where I would use such a variable is in a function
that's using a bash "name reference" (declare -n).  In such a function,
there is an absolute need to ensure that your local variables do not
ever share the name of the output variable, or "pass by reference"
variable, that the caller is supplying.

Thus, in a function "foobar" I would use a local variable like _foobar_i
to *try* to avoid a variable name collision.

Once again, this ONLY applies to functions that are receiving a variable
name passed by a caller and then stored in a local nameref variable.

Now, with that out of the way, and with the almost certain knowledge
that you are going to CONTINUE to ignore me, and CONTINUE to post this
eyeball-searing code....

You tried to do this:   -path "${array[@]}"

This makes no sense.  -path takes ONE argument.  You're passing many.

You need to decide what your find command is supposed to do.  Do you
want it to require a match against ALL of the array elements?  Or only
against ONE of the array elements?  In other words, do you want your
multiple -path filters to be joined with AND or with OR?

If you want an AND join, then build up an argument array like this:

args=( "$dir_brnx" \( )
for p in "${paths[@]}"; do
    args+=( -path "$p" )
done
args+=( \) -prune -type f -printf ... )
find "${args[@]}"

If you want an OR join, it's a tiny bit trickier:

args=( "$dir_brnx" \( )
first=1
for p in "${paths[@]}"; do
    if (( ! first )); then args+=( -o ); fi
    args+=( -path "$p" )
    first=0
done
args+=( \) -prune -type f -printf ... )
find "${args[@]}"

In the first case, you will end up with a find command like this:

    find /dir/brnx \( -path p1 -path p2 \) -prune ...

In the second case:

    find /dir/brnx \( -path p1 -o -path p2 \) -prune ...

I strongly suspect you want the second case, but it's not clear from
my skimming of your code, so I gave both examples.


Reply to: