I need to create both TIF and JPG versions of a large set of images.

All JPG images already exist, but only a part of the TIF images. Is there an easy way to search a directory to find all JPG files that have no corresponding TIF file (i.e. a file with the same name but with different file extension)?

  • Wish I saw this earlier, asked a similar question today. – Rob Oct 27 '11 at 17:47

Perl one-liner:

find . -name '*.jpg'|perl -nle 's/\.jpg//;unless(-f "$_.tif"){print "$_.jpg"}' 

In 63 characters:

find . -name '*.jpg'|perl -pnle 's/.jpg//;-f "$_.tif"||"$_.jpg"' 
| improve this answer | |
  • Interesting... But when I tried it I got the following error (pls note that I don't know perl at all...): Anderss-MacBook-Pro:Temp Anders$ perl hello.pl String found where operator expected at hello.pl line 2, near "name '.jpg'" (Do you need to predeclare name?) String found where operator expected at hello.pl line 2, near "pnle 's/.jpg//;-f "$_.tif"||"$_.jpg"'" (Do you need to predeclare pnle?) syntax error at hello.pl line 2, near "name '.jpg'" Execution of hello.pl aborted due to compilation errors. – Anders Svensson Oct 10 '11 at 21:28
  • I'm guessing you just left out something that you assumed I would know :-). BTW, is there any way of making this recursive to check subdirectories as well, with directory names printed out? – Anders Svensson Oct 10 '11 at 21:30
  • Woops, you run this from the command line, not from inside a perl script. Just cut and paste into terminal when you're in the directory w/ the images. This should cover subdirectories, but the files list as "directory/file1", "directory/file2", etc. – user59328 Oct 10 '11 at 22:25
  • Ok, that's pretty nice! Actually, only the first one worked though, not the second one. That one only listed all the files... Shouldn't you be able to run this in a file though? I read a reeally short intro to perl, where you put the script in a .pl file and ran it from Terminal. That would be good to have in case I need to reuse it, instead of having to paste in this each time... Thanks – Anders Svensson Oct 10 '11 at 23:03
  • Yes, I realized later that the second one was broken. This is really a combination of Unix commands and perl. If you want, you can put it a file called "something.sh" and then do "sh something.sh" (or "bash something.sh"). If you have 'convert' (ImageMagick), you can even convert the jpgs to tiffs. – user59328 Oct 11 '11 at 1:12

Assuming all images are in the images directory and has the .jpg suffix, the following little script will print out all image files that has no corresponding .tif file on UNIX:


find images/ -type f -name "*.jpg" |
while read j; do
  if [ ! -f "$t" ]; then
    echo "Lacking tif file: " $j

Paste this to a file, and save it a folder above the one where your images are stored. You could call it find-images. For example:

├── find-images
└── images/
    ├── 1.jpg
    └── 2.jpg
    └── ...

Now, open Utilities/Terminal.app, and use the cd command to navigate to the folder where your script is, e.g. if the script is on your Desktop, just enter cd Desktop.

Then, enter chmod +x find-images. Now you can run the script by just calling ./find-images.

| improve this answer | |
  • Ok, this sounds sort of doable. I'm on a Mac, which is a kind of Unix, but I'm really new to the Mac. Do I put this script in Terminal or do I somehow create a script file (bash I suppose...)? – Anders Svensson Oct 10 '11 at 16:43
  • @AndersSvensson I added some information about how to run it. KAK, hope you don't mind. – slhck Oct 10 '11 at 18:00
  • This works nicely, and simple enough, thanks. Just a follow-up question: is there any simple way to make it recursive, and check all subdirectories as well? Preferably printing out the name of the directory, like in sections of the result file? – Anders Svensson Oct 10 '11 at 20:34
  • Sorry, just noticed it did actually check recursively... Just ran it on a test folder first which didn't have subdirs... I still have to choose the perl solution, because that worked with all files, this one failed on files with spaces in the names. Thanks though. – Anders Svensson Oct 10 '11 at 23:03
  • @slhck, no worries. – Kusalananda Oct 11 '11 at 8:23

I'll use Python, since it is cross-platform. First put your jpg and tif files in separate folders.

import os

jpgPath = "path/to/jpgs/folder"
tifPath = "path/to/tifs/folder"

jpgList = [item.rsplit(".", 1)[0] for item in os.listdir(jpgPath)]
tifList = [item.rsplit(".", 1)[0] for item in os.listdir(tifPath)]

diffList = [item for item in jpgList if item not in tifList]

print diffList

Then, save this script to a file, somewhere on your hard drive, maybe under the name find-images.

Now, open Utilities/Terminal.app, and enter python /path/to/file. For example, if you saved it on your Desktop, it would be python ~/Desktop/find-images (since ~ is a shortcut to your home folder). Here, you can run a more detailed explanation on running Python files on your Mac.

| improve this answer | |
  • 3
    You need to strip file extensions first, otherwise none of the files will match. I would guess [item.rsplit(".", 1)[0] for item in os.listdir(jpgPath)]... – user1686 Oct 10 '11 at 16:04
  • Hmm, ok thanks, but I have no idea how to use Python. I'm on a Mac, would Python work in Terminal, or what do I do? @grawity: and where would I place this stripping of the extensions command? – Anders Svensson Oct 10 '11 at 16:41
  • @grawity Oh right. Silly me. Edited. @AndersSvensson Python should be pre-installed on your mac. Just type python into Terminal and paste in the above code. – Samuel Oct 10 '11 at 17:26

Ah, I felt like adding this. Here's the solution in Ruby, which prints every image that has no TIF counterpart:

jpg = Dir["*.jpg"]
tif = Dir["*.tif"]    
[jpg, tif].each { |a| a.map!{ |f| f[0..-5]} }
puts jpg - tif

Put it into a file which resides in the same folder as your images, save it as find-images, and run it in Terminal by entering ruby find-images.

If you don't know Ruby, don't ask how it works, might take a while to explain :P

| improve this answer | |
  • 1
    A more generic version: a0, a1 = ARGV[0], ARGV[1]; dir0 = Dir["*.#{a0}"]; dir1 = Dir["*.#{a1}"]; dir0.each {|f| puts f unless dir1.include?(f.sub(/\.#{a0}$/, ".#{a1}"))} – Lri Oct 11 '11 at 9:34
  • @Lri Hah. Pretty neat. Still learning – the parallel assignment is something I have to use more often. – slhck Oct 11 '11 at 9:38



found1=$(find "$PWD" -name "*.$1")
found2=$(find "$PWD" -name "*.$2")
export IFS=$'\n'
for f1 in "$found1"; do
    for f2 in "$found2"; do
        [[ ${base1%.$1} == ${base2%.$2} ]] && continue 2
    echo "$f1"
  • Usage: cd somedir; diffext jpg tif
  • Searches recursively in subdirectories of the current directory
    • Treats files as duplicates even if they were in different directories
| improve this answer | |

One-liner(s) without perl:

With using while loop after find:

find . -name '*.jpg' | while read file ; do test ! -f `dirname $file`/`basename $file .jpg`.tif && echo $file; done

With using (lots of) subshells:

find . -name '*.jpg' -exec sh -c 'test ! -f `echo {} |sed s/\.jpg$/.flac/` && echo {}' \;
| improve this answer | |
  • This would work with file names that have spaces and print the absolute paths: diffexts() { find "$PWD" -name "*.$1" | while read f; do [[ ! -e ${f%.$1}.$2 ]] && echo "$f"; done; } – Lri Oct 28 '11 at 6:06

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.