1

Having issues trying to copy just jpg,png & JPG files starting with IMG_0000 from one directory to another. I have found the correct expression but I am struggling to make it work.

Below I have put the correct Regex as well as my code so far. The directory I am copying from is /root/memory and the target directory is /root/photoarch. Please note that inside /root/memory there are multiple sub-directories and multiple different file types.

Regex:

IMG_[0-9]{4}.[jpg,png,JPG]{3}

Code:

#!bin/bash
mkdir photoarch
find "/root/memory" -regex '.*IMG_[0-9]{4}.[jpg,png,JPG]{3}' -exec cp {} "/root/photoarch"\;
4
  • 1
    [] is a set of characters to look for, which means [jpg,png,JPG]{3} is looking for 3 characters in the set, so this will match any combination of the characters jJpPngG,. You need to use a group instead such as (?:jpg|png|JPG). You should probably use (?:[jJ][pP][eE]?[gG]|[pP][nN][gG]) or (?i)(?:jpe?g|png)(?-i) (assuming bash allows this) instead. If you don't care about IMG being uppercase (you're ok with a case-insensitive search), simply use the case-insensitive flag (typically i) and (?:jpe?g|png). Commented Nov 20, 2017 at 20:27
  • 3
    @ctwheels It's not bash which interprets that regex. It's find. Commented Nov 20, 2017 at 20:46
  • 1
    Joe: A clearer problem statement would be useful. What is happening and how does it differ from your expectations? Commented Nov 20, 2017 at 20:47
  • You need to tell find how to interpret that regex by adding -regextype posix-egrep to the find command Commented Nov 20, 2017 at 20:54

1 Answer 1

4

If you are trying to copy files named IMG_<4-digits>.<jpg|JPG|png>, then your regular expression is wrong, as well as its type (by default find uses Emacs RE, not POSIX ERE).

Regarding the regular expression, you'll have to use alternation instead of character range. For example jpg|png will match either jpg or png. In contrast, [jpg,png]{3} will match any 3-character sequence of j or p or g or , or n, like jjj, j,p, and pnj. Also, you'll have to escape the dot (with \.), otherwise it will match any character.

To use POSIX ERE, set -regextype to posix-extended (to list all types accepted, run find -regextype help).

For case-insensitive matching, you can use -iregex.

find /root/memory -regextype posix-extended -iregex '.*img_[0-9]{4}\.(jpg|png)' -exec cp {} /root/photoarch \;

(The parentheses around jpg|png are necessary because concatenation has higher priority than alternation.)

Sign up to request clarification or add additional context in comments.

4 Comments

Both the original authors and your RE don't match his textual description; he says begin with IMG_0000, but then searches for img_[0-9]{4} which means (assuming all images do indeed have 4 zeroes and then some digits in their name) will never match.
I'm assuming OP wants to match IMG_<4-digits>.<ext> (see my first sentence).
Yeah thanks randomir, this is exactly what I was looking for. Apologies for the poorly worded question as you can see im quite new to stack overflow!
@JoeBloggs, you're welcome, glad to help. And welcome to SO! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.