4

Suppose you have the following problem:

Depending on if a script is executed within a pipe or not, you want to append the -print0 parameter to find.

I can think of at least two ways to do this:

[[ -p '/dev/stdin' ]] && local null_terminated='-print0'
find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \) "$null_terminated"

Or

    if [[ -p '/dev/stdin' ]]; then
        find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \) -print0
    else
        find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \)
    fi

Is there any better way to do this? The question is for bash, but solutions for other shells or portable/standard sh solutions would be welcome as well.

2
  • 2
    Everybody could tell you it's own answer. I think your question is unlikely to be resolved. in my opinion the second form is better though
    – Kiwy
    Mar 14, 2014 at 12:43
  • I agree with Kiwi - too subjective. Personally, though, I might do something like fn() { local pipechk=-print0 ; ... ; [ ! -p /dev/stdin ] && pipechk= ; ... find $args $pipechk ; }
    – mikeserv
    Mar 14, 2014 at 13:10

1 Answer 1

5

The first one won't work as if $null_terminated is empty or unset, find will complain about that empty extra argument.

find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \) $null_terminated

Would work but only if $null_terminated doesn't contain any wildcard characters or characters from IFS.

Doing it:

if [[ -p '/dev/stdin' ]]; then
  extra_args=(-print0)
else
  extra_args=()
fi

find -mindepth 1 -maxdepth 1 ! \( "${args[@]}" \) "${extra_args[@]}"

wouldn't have the problem.

Bourne/POSIXly, you could do:

set -- find . ! -name . -prune ! \( "$@" \)
[ -p /dev/stdin ] && set -- "$@" -exec printf '%s\0' {} +
"$@"

For one argument:

unset extra_arg; [ -p /dev/stdin ] && extra_arg=-print0
find . ! -name . -prune ! \( "$@" \) ${extra_arg+"$extra_arg"}

(note that -print0 is not POSIX).

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