gpt4 book ai didi

linux - 遍历目录中特定扩展名的所有文件

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:36:07 24 4
gpt4 key购买 nike

我写了一个小脚本来解压当前目录中的所有 *.zip 文件,只将 *.srt 文件目录解压到新创建的目录中。然后循环遍历当前目录中的所有 *.mkv 文件以获取它们的名称,然后更改 subs/*.srt 文件名以生成一个新文件名,即与 *.mkv 文件名完全一样。该脚本在只有一个 zip 文件和一个 mkv 文件时有效,但当有更多文件时,它会产生错误的文件名。 我无法追踪为什么会出现这种情况。现在我弄清楚了出现这种情况的时间。

编辑

我设法缩小了以错误方式更改文件名的情况。假设在当前目录中我们有三个 *.mkv 文件:(按字母顺序排序)

$ ls -1a *.mkv
Home.S06E10.1080p.BluRay.x264-PRINTER.mkv
Home.S06E11.1080p.BluRay.x264-PRINTER.mkv
Home.S06E12.1080p.BluRay.x264-PRINTER.mkv

和三个 *.srt 文件:

$ ls -1a *.srt
Home.S06E10.srt
Home.S06E11.BDRip.X264-PRINTER.srt
Home.S06E12.BDRip.X264-PRINTER.srt

当我运行脚本时,我得到:

subs/Home.S06E10.srt -> subs/Home.S06E10.1080p.BluRay.x264-PRINTER.srt
subs/Home.S06E10.1080p.BluRay.x264-PRINTER.srt -> subs/Home.S06E11.1080p.BluRay.x264-PRINTER.srt
subs/Home.S06E11.1080p.BluRay.x264-PRINTER.srt -> subs/Home.S06E12.1080p.BluRay.x264-PRINTER.srt

如你所见,Home.S06E10.srt被使用了两次

#!/usr/bin/env bash

mkdir -p subs
mkdir -p mkv-out
mkdir -p subs-bak
# unzip files, maybe there are subtitles in it...
for zip in *.zip; do
if [ -f "$zip" ]; then
unzip "$zip" -d subs "*.srt" >/dev/null
fi
done

# move all subtitles to subs catalog
for srt in *.srt; do
if [ -f "$srt" ]; then
mv "*.srt" subs
fi
done

mkvCount=(*.mkv)
srtCount=(subs/*.srt)

if [ ${#mkvCount[@]} != ${#srtCount[@]} ]; then
echo "Different number of srt and mkv files!"
exit 1
fi

for MOVIE in *.mkv; do
for SUBTITLE in subs/*.srt; do
NAME=$(basename "$MOVIE" .mkv)
SRT="subs/$NAME.srt"
if [ ! -f "$SRT" ]; then
echo "$SUBTITLE -> ${SRT}"
mv "$SUBTITLE" "$SRT"
fi
done
done

最佳答案

您似乎依赖文件的字典顺序将一个 SRT 与一个 MKV 相关联。如果您只有同一系列的季节-剧集文件,那么我建议采用完全不同的方法:迭代季节和剧集计数器,然后以 S##E## 的形式生成掩码并找到电影和字幕文件。如果找到它们,就移动它们。

for season in {01..06}; do
for episode in {01..24}; do
# Count how many movies and subtitles we have in the form S##E##
nummovies=$(find -name "*S${season}E${episode}*.mkv" | wc -l)
numsubs=$(find -name "*S${season}E${episode}*.srt" | wc -l)
if [[ $nummovies -gt 1 || $numsubs -gt 1 ]]; then
echo "Multiple movies/subtitles for S${season}E${episode}"
exit 1
fi

# Skip if there is no movie or subtitle for this particular
# season/episode combination
if [[ $nummovies -eq 0 ]]; then
continue
fi
if [[ $numsubs -eq 0 ]]; then
echo "No subtitle for S${season}E${episode}"
continue
fi

# Now actually take the MKV file, get its basename, then find the
# SRT file with the same S##E## and move it
moviename=$(find -name "*S${season}E${episode}*.mkv")
basename=$(basename -s .mkv "$moviename")
subfile=$(find -name "*S${season}E${episode}*.srt")
mv "${subfile}" "${basename}.mkv"
done
done

如果您不想重写所有内容,只需更改最后一个循环即可:

  1. 放弃内循环
  2. 改用电影名称并使用 sed 查找特定的 S##E## 子字符串
  3. 像在我的代码中那样使用find 找到一个 SRT 文件
  4. 移动它

这样做的好处是不依赖硬编码的季数/剧集数。我猜了六个季节,没有一个季节超过 26 集。不过,我认为我的代码可以做到并且看起来更简单。

确保只有一个 SRT 文件。拥有零个或多个文件可能只会从 mv 中给出错误,但最好是安全起见。在我的代码中,我使用了单独调用 findwc 来计算行数,但是如果你对 bash-foo 更了解,那么也许有一种方法可以将 find 的输出视为一个数组。

在我的两个建议中,您也可以删除 # movies = # subtitles 的检查。这为您提供了更大的灵 active 。字幕可以位于您想要的任何目录中,但假定电影位于 CWDIR 中。通过 find,您还可以使用 -or 运算符来接受其他扩展名,例如 AVI 和 MPG。

关于linux - 遍历目录中特定扩展名的所有文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48771329/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com