I am trying to run jpegoptim against pictures and at some point in the loop...after let's say 200 iterations, i get "stdin", which requires input to go further.
Is there a way to force the input?
#!/bin/bash
for i in `find . -name "*.jpg" -type f`; do
jpegoptim "$i" >> jpg.log; done
done
First, don't process dynamically generated file lists in a for
loop.
Second, your code is broken - you have 2 done
's.
Third, my apologies, not familiar with the tool, but I'm inclined to think your issue is in a broader piece of the code than presented.
Fourth, (getting minor and nitpicky :) prefer $(
...)
over backticks. There is very rarely a reason not to do so in bash.
Still, almost none of that is relevant to your question, aside from maybe the third thing... See if this helps -
find . -name "*.jpg" -type f |
while read -r file; do jpegoptim "$file"; done >> jpg.log 2>&1
Or possibly better,
find . -name "*.jpg" -type f | xargs jpegoptim >> jpg.log 2>&1
Update
Benjamin W. points out that these break when filenames have embedded newlines, which is entirely true. I consider filenames with embedded newlines a heinous heresy of the highest order, nut sometimes you don't have control of that, so per his entirely valid suggestion:
find . -name "*.jpg" -type f |
while read -r -d '' file; do jpegoptim "$file"; done >> jpg.log 2>&1
or
find . -name "*.jpg" -type f -print0 | xargs -0 jpegoptim >> jpg.log 2>&1
or best, for simplicity and (therefore) safety
find . -name "*.jpg" -type f -exec jpegoptim {} \; >> jpg.log 2>&1
(Please check my syntax on those...)
Though there are still efficiency considerations if you are processing a large number of files. One should also consider the possibility that the target program may or may not be able to multiprocess command-line arguments. Consider the difference between these:
$: find /tmp -type f -exec echo {} \;
/tmp/.mintty-version
/tmp/AdobeARM.log
/tmp/foo
. . .
$: find /tmp -type f | xargs echo
/tmp/.mintty-version /tmp/AdobeARM.log /tmp/foo ...