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

标签 linux bash

我写了一个小脚本来解压当前目录中的所有 *.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/

相关文章:

linux - Alsa麦克风输入高通滤波器禁用

python - Bash/Python 进程匹配

c++ - append 两个字符时出现段错误 - C++

linux - imagemagick RAW 文件识别/转换 - 没有这样的文件或目录(tmp 文件)

linux - 如何在linux系统上查找大文件并删除

bash - 如何在 bash 中导出关联数组(哈希)?

mysql - 如何隐藏用于访问 MySQL 的 bash 脚本中的密码/用户名?

linux - 我可以从 x64 Linux 为 x86 Windows 编写程序集吗?

Java程序运行但不在bash脚本中

linux - 如何测量交换信号的两个Linux脚本之间的最大速度?