4

GNU find allows the use of different regex formats via the -regextype option, but as far as I can tell I have to type out -regextype <whatever> every single time which is onerous.

If one wants a different flavor of regex, chances are that one always wants it rather than switching the type used with every command. The ideal would be to set the preferred regex flavor via a preference file (~/.find_profile) or environment variable ($FIND_OPTS), but I haven't found any indication that this is possible.

How can I set a regextype permanently?

5 Answers 5

2

I haven't done a lot of testing of this, but it seems to work. It takes apart the argument list to find and concatenates the arguments back into another argument list but inserts -regextype posix-awk in front of any -iregex or -regex arguments it finds.

Manipulating the argument list in the shell this way sometimes fails to handle certain quoting constructs properly, but it should work fine in most cases.

Just put this function in your ~/.bashrc or the rc file of whatever shell you run.

find ()
{
    args=
    for arg in $*
    do
        case $arg in
            -iregex|-regex)
                args="$args -regextype posix-awk $arg"
                ;;
            *)
                args="$args $arg"
                ;;
        esac
    done
    set -f
    command find $args
    set +f
}
1
  • This has been working well, with one minor tweak. I bracketed the command call with set -f and set +f to control globbing. Since globbing will have happened before the find () function is invoked, disabling it prevents having to double escape special characters that should not be expanded.
    – blahdiblah
    Nov 15, 2013 at 21:50
1

This answer should be quite safe with regards to whitespace. But perhaps it is bash-specific?

It inserts -regextype posix-extended in front of the first -iregex or -regex. Save this somewhere in your $PATH. And, if you save this as find, make sure you edit the last line (find "$@"), otherwise it will just call itself in an infinite loop

#!/bin/bash
for ((i=1; i<= $#; ++i )) {
    if [[ "-iregex" = "${@:i:1}" ]]; then
        set -- "${@:1:i-1}" "-regextype" "posix-extended" "${@:i}"
        break
    fi
    if [[  "-regex" = "${@:i:1}" ]]; then
        set -- "${@:1:i-1}" "-regextype" "posix-extended" "${@:i}"
        break
    fi
    if [[ "--" = "${@:i:1}" ]]; then
        break
    fi
}
find "$@"

I learned about set --, as a method to edit the command line args, here: from: https://stackoverflow.com/questions/4827690/change-a-command-line-argument-bash

For example, if the fourth argument is -regex, then i is 4 and the new set of command line args should be:

  • the first three original args: "${@:1:i-1}"
  • ... followed by two new args: -regextype and posix-extended
  • ... followed by the fourth and subsequent args: "${@:i}"
1
  • The first two "if [[" can be simplified into one using if [[ ${@:i:1} = -?(i)regex ]] Jul 10, 2019 at 8:34
0

Using an alias for find allows for setting regextype automatically, but limits the other available syntax:

alias find='find -regextype <whatever>'

The problem is that many optional arguments to find now can't be used, because -regextype must be part of the find command's [expression] block:

find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression]

With the above alias, trying to use the symbolic link, debug and optimization options gives the error: find: unknown predicate '-<whatever>' as does specifying a path: find: paths must precede expression: <wherever>. All those options are optional, so find still works, but it's more limited.

0

Another option is a wrapper script around find a la this perl script made explicitly for setting -regextype.

The drawback of this solution is that it's more involved, and somewhat fragile. The linked script doesn't handle -D, for example.

0

I wanted a fairly robust solution that behaved as if find was actually called. But I was OK with bash-specific code. Here's what I came up with.

function __supports_local_dash {
    local - 2> /dev/null
}

if __supports_local_dash; then
    function find {
        {
            local -
            set +xe
        } 2> /dev/null

        local -a ARGS
        for i in "$@"; do
            if [[ $i =~ -i?regex ]]; then
                ARGS+=(-regextype posix-extended)
            elif [[ $i = -regextype ]]; then
                ARGS=("$@")
                break
            fi

            ARGS+=("$i")
        done

        command find "${ARGS[@]}"
    }

    export -f find
else
    echo "WARNING: Version of bash is too old for find shim. Upgrade to >=4.4." 2> /dev/null
fi

I suspect there are more shell options to disable in that set +xe line. Those are the two I use most often that had problems.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .