为了测试的目的,我想计算一个目录中有多少图像文件,通过文件扩展名分隔每个图像文件类型(jpg =“yes”)。这是因为稍后它将对执行操作的另一个脚本有用每个文件扩展名)。我可以仅对 JPEG 文件使用类似以下内容吗?
jpg=""
count=`ls -1 *.jpg 2>/dev/null | wc -l`
if [ $count != 0 ]
then
echo jpg files found: $count ; jpg="yes"
fi
考虑到文件扩展名 jpg、png、bmp、raw 等,我应该使用while
循环来执行此操作吗?
答案1
我的方法是:
- 列出目录中的所有文件
- 提取它们的扩展名
- 对结果进行排序
- 统计每个扩展名出现的次数
有点像这样(最后一次awk
调用纯粹是为了格式化):
ls -q -U | awk -F . '{print $NF}' | sort | uniq -c | awk '{print $2,$1}'
ls
(假设这里有GNU-U
跳过排序的选项作为优化。如果不支持,可以安全地删除它而不影响功能)。
答案2
这会递归遍历文件并计算匹配的扩展名:
$ find . -type f | sed -e 's/.*\.//' | sort | uniq -c | sort -n | grep -Ei '(tiff|bmp|jpeg|jpg|png|gif)$'
6 tiff
7 bmp
26 jpeg
38 gif
51 jpg
54 png
答案3
我建议采用不同的方法,避免可能的分词问题ls
#!/bin/bash
shopt -s nullglob
for ext in jpg png gif; do
files=( *."$ext" )
printf 'number of %s files: %d\n' "$ext" "${#files[@]}"
# now we can loop over all the files having the current extension
for f in "${files[@]}"; do
# anything else you like with these files
:
done
done
files
您可以使用要对每个特定扩展名的文件执行的任何其他命令循环遍历该数组。
更便携 - 或者对于不显式提供数组的 shell - 您可以重复使用 shell 的位置参数数组,即
set -- *."$ext"
然后将${#files[@]}
and替换${files[@]}
为$#
and"$@"
答案4
任何涉及ls
特殊字符(空格和其他符号)的事情都可能会产生意想不到的结果。任何 bashism(如数组)都是不可移植的。任何涉及的事情while read
通常都很慢。
另一方面,find
它非常灵活(有很多过滤选项),它有[至少]两种语法,对于特殊字符来说是安全的......并且它可以在大型目录上很好地扩展。
对于这个例子,我用来-iname
匹配大写和小写的扩展名。我还限制了-maxdepth 1
尊重你的问题的“在当前目录中”。不是计算行数(其中文件名可能包含 CR/LF),而是-print0
在每个文件名的末尾打印一个 NULL 字节...因此| tr -d -c "\000" | wc -l
可以准确地计算文件数(NULL 字节!)。
extensions="jpg png gif"
for ext in $extensions; do
c=$(find . -maxdepth 1 -iname "*.$ext" -print0 | tr -d -c "\000" | wc -c)
if [ $c -gt 0 ]; then
echo "Found $c *.$ext files"
find . -maxdepth 1 -iname "*.$ext" -print0 | xargs -0 -r -n1 DOSOMETHINGHERE
# or # find . -maxdepth 1 -iname "*.$ext" -exec "ls" "-l" "{}" ";"
fi
done
PS甚至-print0 | tr -d -c "\000" | wc -c
可以替换为或。-printf "\000" | wc -c
-printf '\n' | wc -l