无法扩展 stat 命令的 xargs 占位符
Cannot expand xargs placeholder for stat command
简介
假设我有这个文件夹结构
images/
image1.png
image1.webp
image1.avif
image2.jpg
image2.webp
image2.avif
我想 运行 查看每张图片并按以下格式显示其各自的大小:
images/image1.png: 12333 | webp: 6300 | avif: 3400
images/image2.jpg: 15983 | webp: 8497 | avif: 1248
我目前被困在这个尝试中:
find -E images -regex ".*\.(png|jpg)" | xargs -I_ echo 'function getimgsize () { echo $(stat -c "%s" ""); }; 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
上面的脚本产生:
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 _ :
问题
如何修复脚本以使其以正确的格式产生正确的结果?
xargs -I_ echo 'function getimgsize ()...
呃,好绕。如果您发现自己处于这种情况,并且您正在使用 Bash,则说明有问题。写个函数导出就行了
getimgsize() {
stuff to do with ""
srcimg=""
}
export -f getimgsize
input | xargs -n1 bash -c 'getimgsize "$@"' _
不要用单引号写复杂的代码。使用 shellcheck 检查常见错误。不要使用 function name()
- 只需 name()
。 xargs stuff | sh
看起来很奇怪,我认为 xargs sh -c 'stuff'
通常是首选。不要在字符串 xargs -I {} sh -c 'echo {}'
内传递参数 - 更喜欢使用位置参数 xargs -I {} sh -c 'echo ""' - {}
。不要使用 echo $(stuff)
。就stuff
,它已经输出了
在这里使用xargs
真的有什么价值吗?只是循环它。
getimgsize () { stat -c "%s" ""; }
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
我有一个类似的脚本,用于比较不同的压缩格式。这是一个简短的改编:
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
看起来像:
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
如果对应的文件不存在,则打印破折号。您可以更改分隔符等。
简介
假设我有这个文件夹结构
images/
image1.png
image1.webp
image1.avif
image2.jpg
image2.webp
image2.avif
我想 运行 查看每张图片并按以下格式显示其各自的大小:
images/image1.png: 12333 | webp: 6300 | avif: 3400
images/image2.jpg: 15983 | webp: 8497 | avif: 1248
我目前被困在这个尝试中:
find -E images -regex ".*\.(png|jpg)" | xargs -I_ echo 'function getimgsize () { echo $(stat -c "%s" ""); }; 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
上面的脚本产生:
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 _ :
问题
如何修复脚本以使其以正确的格式产生正确的结果?
xargs -I_ echo 'function getimgsize ()...
呃,好绕。如果您发现自己处于这种情况,并且您正在使用 Bash,则说明有问题。写个函数导出就行了
getimgsize() {
stuff to do with ""
srcimg=""
}
export -f getimgsize
input | xargs -n1 bash -c 'getimgsize "$@"' _
不要用单引号写复杂的代码。使用 shellcheck 检查常见错误。不要使用 function name()
- 只需 name()
。 xargs stuff | sh
看起来很奇怪,我认为 xargs sh -c 'stuff'
通常是首选。不要在字符串 xargs -I {} sh -c 'echo {}'
内传递参数 - 更喜欢使用位置参数 xargs -I {} sh -c 'echo ""' - {}
。不要使用 echo $(stuff)
。就stuff
,它已经输出了
在这里使用xargs
真的有什么价值吗?只是循环它。
getimgsize () { stat -c "%s" ""; }
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
我有一个类似的脚本,用于比较不同的压缩格式。这是一个简短的改编:
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
看起来像:
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
如果对应的文件不存在,则打印破折号。您可以更改分隔符等。