使用 bash,如何在 `for` 循环中按 n 个字符进行过滤

使用 bash,如何在 `for` 循环中按 n 个字符进行过滤

问题

我需要根据前 12 个字符从输出中过滤文件,并将其作为输出发送到ffmpeg命令,然后在下一个循环中再次执行此操作。

输入文件。

VID_20190920_195919.mp4
VID_20190920_200821.mp4
VID_20190920_221640.mp4
VID_20190921_141929.mp4
VID_20190921_142236.mp4

在第一个循环中过滤输出(按前 12 个字符,因此按VID_20190920)。

VID_20190920_195919.mp4
VID_20190920_200821.mp4
VID_20190920_221640.mp4

在第二个循环中过滤输出(按前 12 个字符,因此按VID_20190921)。

VID_20190921_141929.mp4
VID_20190921_142236.mp4

ETC。

每个循环(过滤文件列表)都必须导出到cycle.txt,然后文件已由此命令进行处理。

ffmpeg -f concat -i cycle.txt -c copy VID_YYYYMMRR.mp4

然后清理cycle.txt> cycle.txt重复进行下一个循环。

或者是否有更好、最简单的方法来做到这一点?

谢谢。

系统

Linux local 5.0.0-29-lowlatency #31-Ubuntu SMP PREEMPT Thu Sep 12 14:13:01 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

答案1

我认为可以这么做:

unique=($(cat foo | cut -c 5-12 | sort -u))

for i in "${!unique[@]}"; do 
  find *${unique[$i]}* > cycle_$i
done

创建一个仅包含日期的数组:

unique=($(cat foo | cut -c 5-12 | sort -u))

循环遍历数组并找到与每个日期匹配的文件,然后将输出保存到具有索引名称的文件中:

for i in "${!unique[@]}"; do 
  find *${unique[$i]}* > cycle_$i
done

结果:

循环_0.txt

VID_20190920_195919.mp4
VID_20190920_200821.mp4
VID_20190920_221640.mp4

cycle_1.txt

VID_20190921_141929.mp4
VID_20190921_142236.mp4

答案2

假设您的视频文件位于同一目录中,您可以使用以下 bash 命令:

for i in VID_*.mp4; do
  echo ${i%_*}
done | sort -u | while read f; do
  ffmpeg -f concat -i <(echo ${f}*) -c copy "${f}.mp4"  
done

该脚本获取所有视频并从名称中VID_*.mp4删除后缀。 然后循环遍历表单中所有唯一名称并执行。_XXX.mp4
VID_XXXffmpeg

答案3

最终,该解决方案有效。

chars=12
    for file in $(find . -name '*.mp4' -printf "%f\n" | sort -n | cut -c 1-$chars | uniq)
    do
        find . -name '*.mp4' | grep $file | sed "s/^/file '/" | sed "s/$/'/" | sort -n > filein
        ffmpeg -v quiet -safe 0 -f concat -i filein -c copy $file.mp4
    done

似乎需要导出到文件。还是不需要?

信息。

chars,要加入的相同角色数量。

您可以添加-mindepth -maxdepthfind命令,以了解文件夹的深度。

相关内容