1

I am trying to find all files in the directories and sub-directories on Desktop with a file name starting with prac_ followed by two digits and ending in .c or .o

find ./Desktop -type f -name "prac_[0-9][0-9]*" \( -name "*.c" -o -name "*.o" \)

The problem I'm having is that the above command will bring up files like prac_99BLAHBLAH.o when I only want files with the format prac_99.c.

Kusalananda
  • 333,661

2 Answers2

4

Using * in a filename globbing pattern matches any string whatsoever, so it's correct that the name prac_99BLAHBLAH.o matches the pattern prac_[0-9][0-9]*, and one of *.c or *.o.

Instead, use

find ./Desktop -type f -name 'prac_[0-9][0-9].[co]'

The filename globbing pattern [co] matches the single character c or o, so putting it at the end of the pattern used with -name enables you to find filenames that has either character at the end of the name.

Kusalananda
  • 333,661
  • That's the other way round [[:digit:]] is [0123456789] while [0-9] is (or can be) all the characters that sort between 0 and 9 (which can be thousands in some locales on some systems) – Stéphane Chazelas Jun 17 '20 at 07:30
  • @StéphaneChazelas Are you sure? GNU find finds the file called ٠١٢٣٤٥٦٧٨٩ when I use find . -name '*[[:digit:]]*' ! -name '*[0-9]*' in an UTF-8 locale... I was looking at this other answer. – Kusalananda Jun 17 '20 at 08:14
  • Is that OpenBSD? That would make it non-compliant. See https://www.austingroupbugs.net/view.php?id=1078. Oh well, I guess outside the POSIX locale [0123456789] is the only portable option to only match on those 10 digits. – Stéphane Chazelas Jun 17 '20 at 08:38
  • See also https://www.mail-archive.com/austin-group-l@opengroup.org/msg02476.html (where that Q&A you link was mentioned). – Stéphane Chazelas Jun 17 '20 at 08:49
  • @StéphaneChazelas Thanks for the interesting read! Indeed, it's confusing. I'll remove that part of the answer, and will assume that the user knows what they're doing when they use [0-9] in whatever locale they're in. – Kusalananda Jun 17 '20 at 09:01
  • 3
    In that thread, my https://www.mail-archive.com/austin-group-l@opengroup.org/msg02531.html message is probably the most relevant to this, and would suggest nobody (certainly not me) likely knows what they're doing when they use [0-9]. – Stéphane Chazelas Jun 17 '20 at 12:55
1

You're just not restricting the characters between the numbers and file extensions. It can all be a single regex:

find ./Desktop -type f -regex ".*/prac_[0-9][0-9][.][co]"
  • The .*/ at the beginning is because -regex matches on filepaths rather than just filenames.
  • The [.] is a single-character set that matches a period. It's used because a plain . matches any character. Escaping it like \. works too, but I tend to avoid that style because the syntax varies across programming languages (e.g., with an extra escape like \\. or in a raw string like r"\.").
grencez
  • 13
  • Is there a particular reason to place the period in [ ]? – AdminBee Jun 17 '20 at 09:33
  • 1
    @AdminBee The period will match any character unless it is escaped like "." or is a single-character set like "[.]". I prefer the latter because I jump between a lot of domain-specific config languages and tend to forget when "." actually needs to be written as "\." (or r"." or with backticks, etc). – grencez Jun 17 '20 at 10:17
  • 1
    I would recommend placing it in the answer, it is among others these little hints that make the site so useful ... – AdminBee Jun 17 '20 at 10:35