问题描述
想要通过shell脚本完成对某个数据集的处理,具体包括:
- 对该数据集(一个文件夹,如dataset)下的所有子目录进行遍历, 目录结构如下:
dataset
|--real_train
|--0.tar.gz
|--1.tar.gz
|--2.tar.gz
...
|--real_test
|--0.tar.gz
|--1.tar.gz
|--2.tar.gz
...
|--fake_train
|--0.tar.gz
|--1.tar.gz
|--2.tar.gz
...
|--fake_test
|--0.tar.gz
|--1.tar.gz
|--2.tar.gz
...
其中,每个压缩文件.tar.gz解压后的又包括了层数固定的子文件夹,如:
0.tar.gz
|--real
|--8
--23.png
--24.png
--25.png
...
|--9
--256.png
--248.png
--223.png
...
|--11
--203.png
--223.png
--283.png
...
需要一直遍历到最后一层包含多张png图像的目录,如a.tar.gz解压缩后的/real/8/.
- 将每一个目录下的png图片合成一个视频;
- 将合并成的视频统一保存到目录~/video/下,并以该视频原本的目录进行命名以区分,如~/video/real_train_0_real_8.mp4.
思路
- 使用for循环遍历每一个目录,如 for f in `ls`.
当需要仅遍历文件夹时,通过设置ls命令参数for f0 in `ls -F | grep "/$"` 以及 字符串匹配去掉\, f1=${f0%/*}实现;
- 使用上一篇博客ubuntu通过ffmpeg使用shell脚本将同一文件夹下所有图片合并为视频 中的代码将子目录中所有图片合并为视频;
- 通过字符串拼接规定ffmpeg的视频保存路径和名称,从而完成视频保存时的路径和命名要求.
- 每一层的一个目录遍历结束后,都要返回上一层以继续遍历下一个目录.
出错的地方:
- 拼接字符串时双引号外绝不能有空格, 平时空格、符号前后加空格的习惯反而会报错!
- bash不支持/符号,因此保存视频时filename中不能出现\ ,否则ffmpeg会报错 No such file or directory. 应将/符号转移到ffmpeg中使用,如下面的代码所示。
代码
# script to create movie from multiple png files
# taken in choronoligcal order
# real_test, real_train, fake_test, fake_train
for f0 in `ls -F | grep "/$"`
do
f1=${f0%/*}
cd ./$f1
# 3.tar.gz, 6.tar.gz, 8.tar.gz
for f2zip in `ls -rt *.tar.gz`
do
# 解压当前文件
tar -xvf $f2zip
done
# 先解压完全部文件,再提取视频
# 3/, 6/, 9/
for f2 in `ls -F | grep "/$"`
do
# 3, 6, 9
# f2F=${f%/*}
cd ./${f2%/*}
# real
for f3 in `ls`
do
cd ./$f3
# 56, 59, 95, 110
for f4 in `ls`
do
cd ./$f4
# start at 0
count=0
# take all files named shot - something ordered by date
for f in `ls -rt *.png`
do
# get the index in 0000 format
printf $count
printf -v counts "%04d" $count
# link file to a frame_0000 named symbolic link
ln -s $f frame_$counts.png
# increment counter
count=`expr $count + 1`
done
# create movie
# slowed down by factor 5
filename=$f1"_"${f2%/*}"_"$f3"_"$f4
ffmpeg -f image2 -i frame_%04d.png -vcodec mpeg4 -vf "setpts=5*PTS" ~/video/"$filename".mp4
# ffmpeg -i frame_%04d.png movie.mp4
# remove the links
rm frame_*.png
cd ../
done
cd ../
done
cd ../
done
cd ../
done
结果
通过上述的脚本,~/video/下生成的视频如下所示: