Crouze
Crouze

Reputation: 13

Finding files that match regex

So, I'm trying to write a shell script that finds all the files in the current directory that match a fixed regex pattern(in basic regex) given as an argument to my script.

What I came up with is:

find ./ -maxdepth 1 -type f -regex "\.\/"$1""

I have those ./ in the beginning because the find command finds me the files and prints them in ./files format.

The command works if I give the script the argument a.* but if I try to give it something like [0-9]\{2\}[a-zA-Z]* to find me all the files starting with 2 digits, followed by letters, nothing happens and I'm figuring out that it has something to do with escaping special characters but I can't seem to understand why and how to do it properly...

Upvotes: 0

Views: 72

Answers (2)

Sobrique
Sobrique

Reputation: 53478

I would guess this is because your filenames don't start with numbers.

Try running:

 find ./ -depth 1

And look at the paths you get. In particular in the find manpage, note:

This is a match on the whole path, not a search

So you should assume implicit ^ and $ anchors.

You probably want something like:

find ./ -depth 1 -regex "\./[0-9][0-9][A-Za-z]*"

I didn't get any joy with {} as quantifiers, so have opted for the simpler answer that works. This may be down to different versions of find.

Alternatively I might suggest getting perl out, especially as you're only traversing one level:

perl -e 'print join "\n", grep {m/^\d{2}/} glob ( "*" ) '

This uses the subtley different perl grep, which does it match wise on just the filename (expanded from *).

Or you can add a path:

perl -e 'print join "\n", grep {m,/\d{2},} glob ( "./*" )'

Upvotes: 1

Tom Fenech
Tom Fenech

Reputation: 74596

You should quote the argument you're passing, otherwise it may be glob-expanded by the shell before being passed. Also, you will lose the \ as the shell will expand things like \{ to just {.

You should also quote your argument $1 like this:

find_regex() {
    find ./ -maxdepth 1 -type f -regex "\./$1"
}

# usage: find_regex '[0-9]\{2\}[a-zA-Z]*'

This matches a literal ., followed by a /, followed by the argument passed to the function. The way you had it in the question meant that the $1 was outside of double quotes, so you would be subject to glob-expansion and losing slashes for the second time.

Upvotes: 1

Related Questions