Bash - 计算一个文件夹中所有mp3文件的长度
Bash - calculate length of all mp3 files in one folder
我有以下命令,其中 returns 文件名和 mp3 文件的长度:
mp3info -p "%f: %m:%02s\n" *.mp3
如何在 bash 脚本中使用它来 return 给定目录中所有 mp3 文件的总长度(总和)?我想要以下符号:mm:ss
我会采用三步法:
- 而不是打印
filename.mp3: mm:ss\n
,省略文件名并打印总秒数
- 根据结果构建算术表达式,给你总秒数
- 除以 60,向下舍入得到分钟,计算秒的余数。
第一步很简单
mp3info -o '%S'
会完成这项工作。现在,我们希望事物为我们提供
形式的有效数值表达式
时间1+时间2+....
所以,
mp3info -o '%S + '
似乎是明智的。
然后,因为 mp3info 打印的最后一件事将是 +
,让我们添加一个零:
"$(mp3info -o '%S + ') 0"
并在算术表达式中使用该字符串:
total_seconds=$(( $(mp3info -o '%S + ' *.mp3) 0 ))
现在,获取完整的分钟数:
full_minutes=$(( total_seconds / 60 ))
和剩余秒数
seconds=$(( total_seconds % 60 ))
所以整个脚本看起来像
#!/bin/bash
# This code is under GPLv2
# Author: Marcus Müller
total_seconds=$(( $(mp3info -o '%S + ' *.mp3) 0 ))
printf "%02d:%02d\n" $((total_seconds / 60)) $((total_seconds % 60))
mp3info 中的基础计算容易出错,因为元数据不是真实数据。使用 sox(瑞士军队的音频工具)您可以直接从 mp3 文件中获取。
R=0
for a in *.mp3
do
T="$(soxi -D $a 2>-)"
echo $T
[[ "$T" != "" ]] && R="$R + $T"
done
echo $R | bc
如果你想要几个小时
echo "($R) / 60" | bc
对于长长的 mp3 列表,最好将每个循环的持续时间相加
这个 Bourne shell 单行代码,当在仅包含音乐文件的目录中使用时,将以非常高的精度输出它们的总长度(以秒为单位):
LENGTH=0; for file in *; do LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; done; echo "$LENGTH" | bc
修改为仅输出 .mp3 文件的长度(从而避免破坏我们音乐目录中无害的 .docx),它看起来像这样:
LENGTH=0; for file in *.mp3; do if [ -f "$file" ]; then LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; fi; done; echo "$LENGTH" | bc
例如,如果我们想输出只有几个不同文件扩展名的音频的总长度,我们也可以通过添加第二个通配符来做到这一点,同时仍然避免可怕的、可怕的 .docx:
LENGTH=0; for file in *.mp3 *.ogg; do if [ -f "$file" ]; then LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; fi; done; echo "$LENGTH" | bc
当然,必须安装 ffmpeg 才能使用其中任何一个。
这是@albfan 友善答案的变体,带有描述性变量名称和语法突出显示。它适用于目录(相册)的整个目录。
#!/bin/bash
TOTAL=0
for ALBUM in *
do
if [ -d "${ALBUM}" ] ; then
ALBUM_TIME=0
echo ${ALBUM}
# Make `cd` quiet
cd "${ALBUM}" &>/dev/null
for TRACK in *.mp3; do
TRACK_TIME="$(soxi -D "${TRACK}" 2>/dev/null)"
# noisy
# echo "Track duration: $TRACK_TIME"
[[ "$TRACK_TIME" != "" ]] && ALBUM_TIME="$ALBUM_TIME + $TRACK_TIME"
done
# Convert summation to a single number for efficiency
ALBUM_TIME=`echo $ALBUM_TIME | bc`
# This has to be two stmts?
echo -n "Album time (min): "; echo 'scale=2;' ${ALBUM_TIME} / 60 | bc
echo # line break
TOTAL="$TOTAL + $ALBUM_TIME"
cd ..
fi
# Evaluate the expression
TOTAL=`echo $TOTAL | bc`
done
echo -n "Total time (hrs): "; echo 'scale=2;' ${TOTAL} / 3600 | bc
我有以下命令,其中 returns 文件名和 mp3 文件的长度:
mp3info -p "%f: %m:%02s\n" *.mp3
如何在 bash 脚本中使用它来 return 给定目录中所有 mp3 文件的总长度(总和)?我想要以下符号:mm:ss
我会采用三步法:
- 而不是打印
filename.mp3: mm:ss\n
,省略文件名并打印总秒数 - 根据结果构建算术表达式,给你总秒数
- 除以 60,向下舍入得到分钟,计算秒的余数。
第一步很简单
mp3info -o '%S'
会完成这项工作。现在,我们希望事物为我们提供
形式的有效数值表达式时间1+时间2+....
所以,
mp3info -o '%S + '
似乎是明智的。
然后,因为 mp3info 打印的最后一件事将是 +
,让我们添加一个零:
"$(mp3info -o '%S + ') 0"
并在算术表达式中使用该字符串:
total_seconds=$(( $(mp3info -o '%S + ' *.mp3) 0 ))
现在,获取完整的分钟数:
full_minutes=$(( total_seconds / 60 ))
和剩余秒数
seconds=$(( total_seconds % 60 ))
所以整个脚本看起来像
#!/bin/bash
# This code is under GPLv2
# Author: Marcus Müller
total_seconds=$(( $(mp3info -o '%S + ' *.mp3) 0 ))
printf "%02d:%02d\n" $((total_seconds / 60)) $((total_seconds % 60))
mp3info 中的基础计算容易出错,因为元数据不是真实数据。使用 sox(瑞士军队的音频工具)您可以直接从 mp3 文件中获取。
R=0
for a in *.mp3
do
T="$(soxi -D $a 2>-)"
echo $T
[[ "$T" != "" ]] && R="$R + $T"
done
echo $R | bc
如果你想要几个小时
echo "($R) / 60" | bc
对于长长的 mp3 列表,最好将每个循环的持续时间相加
这个 Bourne shell 单行代码,当在仅包含音乐文件的目录中使用时,将以非常高的精度输出它们的总长度(以秒为单位):
LENGTH=0; for file in *; do LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; done; echo "$LENGTH" | bc
修改为仅输出 .mp3 文件的长度(从而避免破坏我们音乐目录中无害的 .docx),它看起来像这样:
LENGTH=0; for file in *.mp3; do if [ -f "$file" ]; then LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; fi; done; echo "$LENGTH" | bc
例如,如果我们想输出只有几个不同文件扩展名的音频的总长度,我们也可以通过添加第二个通配符来做到这一点,同时仍然避免可怕的、可怕的 .docx:
LENGTH=0; for file in *.mp3 *.ogg; do if [ -f "$file" ]; then LENGTH="$LENGTH+$(ffprobe -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$file" 2>/dev/null)"; fi; done; echo "$LENGTH" | bc
当然,必须安装 ffmpeg 才能使用其中任何一个。
这是@albfan 友善答案的变体,带有描述性变量名称和语法突出显示。它适用于目录(相册)的整个目录。
#!/bin/bash
TOTAL=0
for ALBUM in *
do
if [ -d "${ALBUM}" ] ; then
ALBUM_TIME=0
echo ${ALBUM}
# Make `cd` quiet
cd "${ALBUM}" &>/dev/null
for TRACK in *.mp3; do
TRACK_TIME="$(soxi -D "${TRACK}" 2>/dev/null)"
# noisy
# echo "Track duration: $TRACK_TIME"
[[ "$TRACK_TIME" != "" ]] && ALBUM_TIME="$ALBUM_TIME + $TRACK_TIME"
done
# Convert summation to a single number for efficiency
ALBUM_TIME=`echo $ALBUM_TIME | bc`
# This has to be two stmts?
echo -n "Album time (min): "; echo 'scale=2;' ${ALBUM_TIME} / 60 | bc
echo # line break
TOTAL="$TOTAL + $ALBUM_TIME"
cd ..
fi
# Evaluate the expression
TOTAL=`echo $TOTAL | bc`
done
echo -n "Total time (hrs): "; echo 'scale=2;' ${TOTAL} / 3600 | bc