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.

1

2 Answers 2

3

You can try this:

shopt -s globstar
for f in **/*.lri; do 
  [[ ! $(find . -name "$(basename "${f%%.lri}").dng") ]] && realpath "$f"
done
2
  • If the file.dng is supposed to be in the same directory as the file.lri, then the loop body can be more simply [[ -f "${f%.lri}.dng" ]] || realpath "$f" Jan 12, 2021 at 22:58
  • @Freddy right, done! Jan 13, 2021 at 19:54
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
4
  • 1
    Parsing Ls has many pitfalls. What to use instead?
    – Quasímodo
    Jan 12, 2021 at 20:10
  • @Quasímodo: That is a good point but in practice I find it hard to create a filename that causes real problems in the processing of this specific command. Interpreting the output can be tricky but it is essentially correct I believe. Jan 12, 2021 at 22:18
  • Unfortunately this does not work recursively ls -r *.lri | perl -nle 's/\.lri$/.dng/; print unless -e ' ls: cannot access '*.lri': No such file or directory
    – user394
    Jan 13, 2021 at 19:16
  • @user394: See update at end for recursive version Jan 14, 2021 at 15:19

You must log in to answer this question.

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