6

I have work with find before to find all specific files in a folder and subfolder and do something about it

For example, I did use

find /folder/ -name '*.txt' -exec chmod 666 {} \;

This code to easy change write access to every text file in the folder.

Now I was going to try to convert every jpg(even JPG) to gif in the same way but not sure if that is so easy. When I try with the convert command tools it wants to have an inputfilename and output filename but I do not think find give that so maybe find is not the right Tools to use?

5
  • 1
    Do you mean X amounts of jpegs so you get 1 GIF. Or 1 gif for every jpeg?
    – Rinzwind
    Jul 27, 2019 at 13:32
  • 1
    Note that your example makes the *.txt files world-writable with that mode 666. That is almost never a good idea.
    – marcelm
    Jul 28, 2019 at 9:10
  • 1
    Why do you want GIF in this day and age except for animation? Jul 28, 2019 at 12:28
  • Note that GIF supports upto 256 colours from a 24-bit palette. JPG supports 24-bit colours. You are likely to introduce dithering artefacts doing this
    – CSM
    Jul 28, 2019 at 16:52
  • Well that is true that is not good idea to make every textfile 666 but when I did use this code I did have to do that to make some script work. Some file is GIF as default and some was JPG, that I have done now is just use at it is.
    – Cazz
    Jul 28, 2019 at 18:29

3 Answers 3

8

Find can be used for this, but I find it easier to use the shell instead. If your files are all in the same directory (no subdirectories) you can just do:

for f in /path/to/dir/*jpg /path/to/dir/*JPG; do
    convert "$f" "${f%.*}.gif"
done

The ${var%something} syntax will remove the shortest match for the glob something from the end of the variable $var. For example:

$ var="foo.bar.baz"
$ echo "$var : ${var%.*}"
foo.bar.baz : foo.bar

So here, it is removing the final extension from the filename. Therefore, "${f%.*}.gif" is the original file name but with .gif instead of .jpg or .JPG.

If you do need to recurse into subdirectories, you can use bash's globstar option (from man bash):

globstar
    If set, the pattern ** used in a pathname expansion con‐
    text will match all files and zero or  more  directories
    and  subdirectories.  If the pattern is followed by a /,
    only directories and subdirectories match.

You can enable it with shopt -s globstar:

shopt -s globstar
for f in /path/to/dir/**/*jpg /path/to/dir/**/*JPG; do
    convert "$f" "${f%.*}.gif"
done
1
  • Ahh globstar was something new for me, and it works greate that you give me.
    – Cazz
    Jul 27, 2019 at 17:56
5

You can indeed use find - with a shell wrapper that calls the appropriate convert command and generates the output file using paramemter substitution. Ex.

find . -name '*.jpg' -execdir sh -c '
  for f; do convert -verbose "$f" "${f%.*}.gif"; done
' find-sh {} +

Change -name to -iname to include the .JPG extension (although note that the replacement .gif extension will be lower case regardless).

2
  • wow nice, nice to know if I need to change something easy and fast
    – Cazz
    Jul 27, 2019 at 17:56
  • Why ask find to combine a whole bunch of results into a single commandline, only to split them apart again?
    – Ben Voigt
    Jul 28, 2019 at 5:25
1

There's another tool in ImageMagick, mogrify, that's designed to make batch processing easy. This does what you want:

shopt -s globstar
mogrify -format gif **/*.jpg
0

You must log in to answer this question.

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