For a variant that does both and and not:
findn() (
if [ -t 1 ]; then # if the output goes to a terminal
action=-print # simple print for the user to see
else
action=-print0 # NUL-delimited records so the output can be post-processed
fi
first=true
for arg do
if "$first"; then
set -- "$@" '('
first=false
else
set -- "$@"
fi
if [ "$arg" = ! ]; then
set -- "$@" !
else
case $arg in
(*[][*?\\]*)
# already contains wildcard characters, don't wrap in *
set -- "$@" -iname "$arg"
;;
(*)
set -- "$@" -iname "*$arg*"
;;
esac
fi
shift
done
"$first" || set -- "$@" ')'
exec find . "$@" "$action"
)
For the filenames that contain both foo
and bar
and not baz
.
In that variant, I also made it so that if the argument contained a wildcard character, it was taken as-is, so you can do:
findn foo ! 'bar*'
To look for files that do not start with bar. If you're using the zsh
shell, you can make an alias:
alias findn='noglob findn'
To disable globbing on that command which allows you to write:
find foo ! bar*
You may want to make that a script (here a sh
script is enough as that syntax is POSIX) instead of a function, so it can be called from anywhere instead of just your shell.