0

I have a directory with several thousand files. Many of them are images where the filename begins with the image's resolution. The height and width of the images can be two, three, four or five digits long. For example:

 - 986x1088_lalbslj.jpg
 - 2043x924_fjnndkk.jpg
 - 9560x12643_fjknfd.jpg
 - 24x24_dnjkan.jpg

I'd like to collect all these images in a new directory (say ./images/). Sounds simple enough.
The simple regex [0-9]+x[0-9]+.* matches these filenames, but as far as I've understood, you can't use regex with mv.
Ideally, I'd like something like this to work: mv [0-9]+x[0-9]+.* images, but of course, it doesn't.

It seems this questions has been asked a lot before, and I've already looked at several dozen (literally!) similar threads on this and other StackExchanges, but sadly I haven't yet seen an answer that helps me. Most of the time, the accepted answers are simply explaining that mv uses globs and not regex, or suggesting a corresponding glob that helps the author, but which doesn't work in my case. So I'm trying my luck by asking my own question – I hope that's OK.

I can't seem to condense my pattern into any reasonable glob, and regex doesn't work with mv, so what do I do?
Surely this must be possible somehow?!

Thank you very much for all your kind replies!

2 Answers 2

2

You can use extended globs:

If the extglob shell option is enabled using the shopt builtin, several extended pattern matching operators are recognized. In the following description, a pattern-list is a list of one or more patterns separated by a ‘|’. Composite patterns may be formed using one or more of the following sub-patterns: [...]

+(pattern-list)
Matches one or more occurrences of the given patterns.

So:

shopt -s extglob
mv +([0-9])x+([0-9])* ./images
3
  • I like this answer but will prefer to replace [0-9] with [[:digit:]].
    – unxnut
    Jun 10, 2020 at 3:22
  • @unxnut: any reason for your preference ?
    – Cbhihe
    Jun 10, 2020 at 7:00
  • It's simple. However, the one I proposed is closer to what was asked (between two and five digits on each side of x).
    – unxnut
    Jun 10, 2020 at 12:34
1

You can use the following loop to achieve your objective:

for i in *
do
    echo "$i" | grep -qE "^[[:digit:]]+x[[:digit:]]+.*" && mv "$i" images
done

You can change the regular expression to specify between 2 and 5 digits as follows:

for i in *
do
    echo "$i" | grep -qE "^[[:digit:]]{2,5}x[[:digit:]]{2,5}.*" && mv "$i" images
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.