1

I bought a special digital camera that saves a proprietary image format, which ends in .lri. The company has a desktop program to render .lri files into standard jpg and dng files.

I'm finding that as I look at my directory where I've saved this files, I've missed converting some files. However my ability to visually notice missing pairs, the number of files, and the nested directory structure makes it difficult to definitely find all the files I want to convert.

I'm looking for a shell command to find files of extension .lri when there exists no matching filename of .dng (I'm not worried about jpg files presently). For instance, if I have L16_04198.lri, I should have L16_04198.dng, if I was diligent in my work months or years ago.

Edit Two constraints that I failed to mention: The files are in a nested directory structure, so this needs to be a recursive search. Also, I have spaces in the names of directories, so it needs to be able to handle that, also.

So I need a command or script that will report to me the filename L16_04198.lri, if it finds no L16_04198.dng, anywhere in the nested subdirectory structure (I may have rendered the file, but put it in the wrong subdirectory).

I'm familiar with the find command, but I'm not sure how to look for "not" a filename, and report if that name is not found.

user394
  • 14,404
  • 21
  • 67
  • 93

2 Answers2

3

You can try this:

shopt -s globstar
for f in **/*.lri; do 
  [[ ! $(find . -name "$(basename "${f%%.lri}").dng") ]] && realpath "$f"
done
1

tl;dr:

find . -name "*.txt" | perl -nle 's/\.txt$/.foo/; print unless -e' | cat -v

Here's an example using Perl

Note that we have a c.foo missing

$ ls
a.foo  a.txt  b.foo  b.txt  c.txt

We can find it this way

$ ls *.txt | perl -nle 's/\.txt$/.foo/; print unless -e '
c.foo

c.foo is missing


Update: dealing with filenames that contain metacharacters etc

Consider this set of filenames that contain spaces, newlines and pipe symbols

$ ls *txt
 a.txt   b.txt   c.txt  'd d.txt'  'e'$'\r''e.txt'  'f'$'\n''f.txt'  'g|g.txt'   taskmaster.txt

In practice Perl doesn't seem to have a problem parsing the output of ls:

$ ls *txt | perl -nle 's/\.txt$/.foo/; print unless -e'
c.foo
d d.foo
e.foo
f
f.foo
g|g.foo
taskmaster.foo

Obviously if your filenames contain control characters you may need to make them more visible

$ ls *txt | perl -nle 's/\.txt$/.foo/; print unless -e' | cat -v
c.foo
d d.foo
e^Me.foo
f
f.foo
g|g.foo
taskmaster.foo

If you want this to work recursively

$ find . -name "*.txt" | perl -nle 's/\.txt$/.foo/; print unless -e' | cat -v
./c.foo
./d d.foo
./e^Me.foo
./f
f.foo
./g|g.foo
./h*h.foo
./temp/j.foo