我正在编写一个脚本来对一个非常大的音乐收藏进行排序。大约有 22000 张专辑,混合了 FLAC、WAV、AIFF、M4A(AAC 和 ALAC)。
到目前为止,我可以按文件类型排序并获取每种类型的总大小。
ftypes=$(find . -type f | grep -iE ".*\.[a-zA-Z0-9]*$" | sed -e 's/.*\(\.[a-zA-Z0-9]*\)$/\1/' | sort -f | uniq -i)
for ft in $ftypes
do
echo -n "$ft "
find . -name "*${ft}" -print0 | xargs -0 du -hc | grep total | awk '{print $1}'
done
我想编辑它以按文件类型获取文件数量以及总大小。
现在,M4A 文件可以是 AAC 或 ALAC,我想知道每种文件有多少个。
我可以使用以下命令查找并打印 ALAC 文件列表
find . -name \*.m4a | while read file; do avprobe "$file" 2>&1 | grep -q 'Audio: alac' && echo "$file"; done
但我不知道如何获取文件总数和大小,而不是文件名列表,并将其全部合并到一个脚本中。
基本上,我想输出:
- 文件类型列表
- 按文件类型划分的文件数
- 按文件类型划分的总大小
- M4A AAC总数&总大小
- M4A ALAC 总数&总大小
根据其工作效果,我可能会考虑使用它根据输出将文件排序到目录中。
答案1
你应该将你的目标分解为几个更容易解决的步骤。这将有两个优点:
- 会比较容易解决,
- 生成的代码将更清晰且更可重用。
下面的脚本基本上遵循以下步骤:
- 生成原始统计文件。一种简单的方法是将文件大小和文件名附加到以原始文件扩展名命名的临时文件中。因此,如果您的文件大小
/path/to/foo.mp3
为 3000000,它将附加到3000000 /path/to/foo.mp3
名为 的临时文件的末尾mp3
。 - 处理具体案件。在这里,它将处理临时文件
m4a
并创建其他两个文件m4a_aac
,并m4a_alac
基于您在问题中给出的测试。 - 生成输出。所有需要的信息现在都可用,它只需要:
- 统计每个临时文件中的行数以确定该类型文件的数量,
- 将每个大小相加即可得到该类型文件的总大小。
这是脚本:
#!/bin/sh
# This script takes the searched directory as first parameter.
# For instance: ./this-script.sh ~/Music
: ${1:?"You must pass the search directory as first parameter."}
searchdir="$1"
# Create a temporary directory
statsdir=""
trap 'rm -rf $statsdir' EXIT
statsdir=$(mktemp -d "/tmp/tmp.XXXXXXXXXX") || exit 1
# Generate one listing file per extension
awkscript='/\.[[:alnum:]]+$/ {print $0 >statsdir"/"$(NF)}'
# For Linux: stat -c "%s %n"
# For Mac: stat -f "%z %N"
find "$searchdir" -type f -exec stat -f "%z %N" {} + | \
awk -F '.' -v statsdir="$statsdir" "$awkscript"
# Distinguish between m4a/AAC and m4a/ALAC
if [ -f "$statsdir/m4a" ]; then
input="$statsdir/m4a"
while IFS= read -r line; do
filename=${line#* }
if avprobe "$filename" 2>&1 | grep -q 'Audio: alac'; then
echo "$line" >> "$statsdir/m4a_alac"
else
echo "$line" >> "$statsdir/m4a_aac"
fi
done < "$input"
rm "$statsdir/m4a"
fi
# Generate and display result
{
printf "Type Count Size\n"
for extension in $(ls "$statsdir"); do
count=$(wc -l "$statsdir/$extension" | cut -d ' ' -f 1)
totalsize=$(awk '{s+=$1} END {print s}' "$statsdir/$extension")
printf "%s %d %d\n" "$extension" "$count" "$totalsize"
done
} | column -t