5

I have a list of files inside a directory and I want to make a bash script which uses a regular expression to check if every file name inside it has this syntax:

xxxx_xxxx_xx_xx

Where x are numbers.

Edit: I only need with the regex

2 Answers 2

8

How about

#/usr/bin/env bash
for f in *
do
  [[ $f =~ [0-9]{4}_[0-9]{4}_[0-9]{2}_[0-9]{2} ]] || 
    echo "File $f does not match"
done

The regular expression checks for any digit ([0-9]). The numbers in curly braces are the number of repetitions so [0-9]{4} will match any 4 digits.

I would recommend you don't use bash for this but find instead. It will probably be faster, and it is certainly more portable (not all shells can deal with regular expressions):

find -regextype posix-egrep -not -regex '\./[0-9]{4}_[0-9]{4}_[0-9]{2}_[0-9]{2}'
6
  • I can’t construct a scenario that causes your find command to break, but I still believe (on general principles) that the regex should probably be quoted, for safety. Jul 11, 2014 at 14:50
  • @Scott I tend to agree with such precautionary quoting but I don't know of any shell that would choke on that. Still, as you said, better safe than sorry. Quotes added.
    – terdon
    Jul 11, 2014 at 15:31
  • OK, I had my n+1 th injection of caffeine, and I figured it out. It’s not an issue of the shell choking, per se. If there is a file in the current directory with a name like 5{4}_3{4}_0{2}_9{2} (and you don’t have shell globbing turned off), then \./[0-9]{4}_[0-9]{4}_[0-9]{2}_[0-9]{2} (your regex) will expand to ./5{4}_3{4}_0{2}_9{2}, and your find will match only ./5555_3333_00_99 (if it exists). … … (BTW, 5309 is the last four digits of Jenny’s phone number.) Jul 11, 2014 at 15:50
  • @Scott ah, yes, well found! Who's Jenny? Or should I not ask?
    – terdon
    Jul 11, 2014 at 16:29
  • Seriously? Oh, I see; you don’t live in a primarily English-speaking country. Here you go. Jul 11, 2014 at 16:33
1

It’s clunky, but this should be very portable:

#!/bin/sh
for x in *
do
    case "$x" in
        [0-9][0-9][0-9][0-9]_[0-9][0-9][0-9][0-9]_[0-9][0-9]_[0-9][0-9])
            echo "$x matches"
            ;;
        *)
            echo "$x  doesn’t match"
    esac
done
#                       And, to be annoyingly complete,
for x in .*
do
    echo "$x  doesn’t match"
done
1
  • Same regex i used, btw i think that the solution provided by @terdon is cleaner. Thanks anyway! Jul 11, 2014 at 18:51

You must log in to answer this question.

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