Intro
Let's say I have this folder structure
images/
image1.png
image1.webp
image1.avif
image2.jpg
image2.webp
image2.avif
And I want to run through each image and show its respective size in a following format:
images/image1.png: 12333 | webp: 6300 | avif: 3400
images/image2.jpg: 15983 | webp: 8497 | avif: 1248
I am currently stuck at this attempt:
find -E images -regex ".*\.(png|jpg)" | xargs -I_ echo 'function getimgsize () { echo $(stat -c "%s" "$1"); }; srcimg="_"; srcimgnoext=$(echo "$srcimg" | sed -E "s/.jpg|.png//g"); srcimgsize=$(getimgsize "$srcimg"); webpsize=$(getimgsize "$srcimgnoext.webp"); avifsize=$(getimgsize $srcimgnoext.avif); echo "$srcimg: $srcimgsize | webp: $webpsize | avif: $avifsize"' | sh
The script above yields:
stat: cannot stat '_': No such file or directory
stat: cannot stat '_.webp': No such file or directory
stat: cannot stat '_.avif': No such file or directory
stat: cannot stat '': No such file or directory
stat: cannot stat '_': No such file or directory
stat: cannot stat '_.webp': No such file or directory
stat: cannot stat '_.avif': No such file or directory
_ :
function getstat () { echo ; }; srcimg=_; srcimgnoext=_; srcimgsize=; webpsize=; avifsize=; echo _ :
Question
How to fix the script so that it yields the proper results in a proper format?
CodePudding user response:
xargs -I_ echo 'function getimgsize ()...
Ugh, so convoluted. If you find yourself in such a situation, and you are using Bash, it means something is wrong. Just write the function and export it.
getimgsize() {
stuff to do with "$1"
srcimg="$1"
}
export -f getimgsize
input | xargs -n1 bash -c 'getimgsize "$@"' _
Do not write complicated code in single quotes. Use shellcheck to check for common mistakes. Do not use function name()
- just name()
. The xargs stuff | sh
looks odd, I think xargs sh -c 'stuff'
is commonly preferred. Do not pass arguments inside strings xargs -I {} sh -c 'echo {}'
- prefer to use positional arguments xargs -I {} sh -c 'echo "$1"' - {}
. Do not use echo $(stuff)
. Just stuff
, it already outputs it.
Is there really any value in using xargs
here? Just loop it.
getimgsize () { stat -c "%s" "$1"; }
find -E images -regex '.*\.(png|jpg)' |
while IFS= read -r srcimg; do
srcimgnoext=$(<<<"$srcimg" sed -E 's/\.(jpg|png)$//')
srcimgsize=$(getimgsize "$srcimg")
webpsize=$(getimgsize "$srcimgnoext.webp")
avifsize=$(getimgsize "$srcimgnoext.avif")
echo "$srcimg: $srcimgsize | webp: $webpsize | avif: $avifsize"
done
CodePudding user response:
I have a script similar to this, for comparing different compression formats. Here's a short adaption:
find . -mindepth 1 -maxdepth 1 -type f \
\( -name '*.png' -o -name '*.jpg' \) -print0 |
while IFS= read -rd '' file; do
file=${file#./}
name=${file%.*} ext=.${file##*.}
list=$name
for i in "$ext" .webp .avif; do
size=$([[ -e "$name$i" ]] && stat -c %s "./$name$i")
list ="$i: ${size:--} | "
done
echo "${list% | }"
done |
column -t |
sort -k1,1
Looks like:
dragon.jpg: 111626 | .webp: - | .avif: -
foo1.png: 20088 | .webp: 5000 | .avif: 295040
foo2.png: 12254 | .webp: 13320 | .avif: 74036
foo3.png: 19600 | .webp: - | .avif: 101388
foo4.png: 160800 | .webp: 353883 | .avif: 25792
foo5.png: 397100 | .webp: 325920 | .avif: 59249
It prints a dash if the corresponding file doesn't exist. You can change the delimiters etc.