5

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)?

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

6 Answers 6

3

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"' 
5
  • 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. Oct 10, 2011 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? Oct 10, 2011 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, 2011 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 Oct 10, 2011 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, 2011 at 1:12
7

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:

#!/bin/sh

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

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.

7
  • 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...)? Oct 10, 2011 at 16:43
  • @AndersSvensson I added some information about how to run it. KAK, hope you don't mind.
    – slhck
    Oct 10, 2011 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? Oct 10, 2011 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. Oct 10, 2011 at 23:03
  • @slhck, no worries. Oct 11, 2011 at 8:23
6

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.

3
  • 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)]... Oct 10, 2011 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? Oct 10, 2011 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, 2011 at 17:26
2

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

2
  • 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, 2011 at 9:34
  • @Lri Hah. Pretty neat. Still learning – the parallel assignment is something I have to use more often.
    – slhck
    Oct 11, 2011 at 9:38
2

diffext

#!/bin/bash

found1=$(find "$PWD" -name "*.$1")
found2=$(find "$PWD" -name "*.$2")
export IFS=$'\n'
for f1 in "$found1"; do
    base1=${f1##/}
    for f2 in "$found2"; do
        base2=${f2##/}
        [[ ${base1%.$1} == ${base2%.$2} ]] && continue 2
    done
    echo "$f1"
done
  • 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
1

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 {}' \;
1
  • 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, 2011 at 6:06

You must log in to answer this question.

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