从文件名中提取信息以实现自动复制

4

这是我在StackOverflow上的第一篇文章,请温柔点。:)

我有一个Linux服务器,我会下载电视节目并手动将文件移动到它们各自的文件夹中,以便我的Plex服务器利用。我想自动化这个过程。我已经做到了以下这一步。

文件命名规则 Show.Name.SeasonNumberEpisodeNumber.HDTV.X264.etc...

例如:Almost.Human.S01E01.720p.HDTV.X264.mkv

注意:演出名称可以具有不同的长度,并且在名称中每个单词之间用“。”分隔。

我能够从文件名中提取显示文件夹名称。

#!/bin/bash
readonly FILEPATH=~/downloads
readonly SAVEPATH=~/shows

for file in $FILEPATH/*.mkv
do
#Get foldername from filename (everything before .S0 is foldername
        foldername=$(basename "${file%.S0*}" | tr '.' ' ')
#Need to convert extracted season info into folder name ex. S01 = Season 1
#       seasonfolder=$(basename "${file}" | sed -e 's/^[^S0]*//;')

#Copy the file to the path we built.
#Auto-create folder if it doesn't exist?

#       cp $file  "$SAVEPATH/$foldername/#seasonfolder"

done

问题:

  • 我还想从文件名中提取季节信息,并使用它来构建其余的文件夹路径。每个文件都有一个SxxExx部分,我可以用它来获取季节信息。例如,我将S01转换为第1季,以成为文件夹路径的一部分。

生成的复制命令将类似于以下内容(使用上述文件名)

cp Almost.Human.S01E01.720p.HDTV.X264.mkv shows/Almost Human/Season 1

我不太懂sed或正则表达式,无法正确使用语法。经过多次搜索,没有人在任何示例中做到这一点,我可以“借鉴”。

提前感谢!

更新

非常感谢Janos!他不仅提供了一个很好的解决方案,还帮助我更好地理解了使用正则表达式的方法。

我对最终产品进行了一些更改。经过了解Plex的命名约定要求,我调整了正则表达式以适应,并内置了“文件存在”检查以避免不必要的传输。

这是最终结果,我将在今晚添加到CRON中。

#!/bin/bash
readonly FILEPATH=~/downloads
readonly SAVEPATH=~/shows

for file in $FILEPATH/*.mkv
do
        dfile="$SAVEPATH/$(basename "$file" | sed -e 's/\./ /g' -e 's?\(.*\) [Ss]\([0-9][0-9]\)[Ee]\([0-9][0-9]\) .*?\1/Season \2/\1 - S\2E\3.mkv?')"

        if [ ! -f "$dfile" ]

        then
                cp -v "$file" "$dfile"
                mkdir -p "$(dirname "$dfile")"
        else
                echo "file exists "$dfile""
        fi

done

欢迎来到SO!请尽量将帖子限制在一个问题上。关于文件夹,您可能会对https://dev59.com/0G445IYBdhLWcg3wWY8U感兴趣。 - Jeff
虽然你很难解释输入和输出的约定,但给出实际的输入和“你想要得到的”输出示例会更有用。 - Mihai
谢谢!已更新并附上示例,删除了第二个问题。(感谢Jeff,我会使用那篇帖子并为文件名解决问题) - JonShado
1
+1 鼓励好问题和接受建议的能力;-)祝大家好运。 - shellter
我知道这个问题已经存在很长时间了,但是我开发了一个Python ,可以为您完成这项任务。 - Divij Bindlish
显示剩余2条评论
1个回答

2
你可以这样做:
for file in $FILEPATH/*.mkv; do
    # get the destination filename
    dfile="$SAVEPATH/$(basename "$file" | sed -e 's/\./ /g' -e 's?\(.*\) S0\([0-9]\)E\([0-9][0-9]\) .*?\1/Season \2/Episode \3.mkv?')"

    # create the destination directory
    mkdir -p "$(dirname "$dfile")"

    cp "$file" "$dfile"
done

这将创建类似于以下的文件名:
Almost Human/Season 1/Episode 01.mkv

为了使文件名像这样:
Almost Human/Season 1/Almost Human Episode 01.mkv

那么将 sed 更改为以下内容:

sed -e 's/\./ /g' -e 's?\(.*\) S0\([0-9]\)E\([0-9][0-9]\) .*?\1/Season \2/\1 Episode \3.mkv?

在这个解决方案中,关键在于捕获括号\(...\)中的相关部分,并使用\1表示第一个\(...\)\2表示第二个,以此类推。请保留HTML标签。

我喜欢它!谢谢你的回答!我认为唯一的改变是(我正在努力自己解决),就是将节目标题添加到剧集名称中,以保持所有文件名唯一。否则,对于每个节目名称都会有一个第1集。我很确定Plex会更喜欢Almost Human Episode 7.mkv这样的格式。(或者带有连接符的Almost_Human_Episode7.mkv) - JonShado

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接