递归重命名与正则表达式匹配的子目录


11

我有一个媒体服务器,其文件夹名为Series。(/media/Expansion2/Series/

在其中,我有(惊讶!)电视连续剧。这些只是节目名称,例如,/media/Expansion2/Series/The Big Bang Theory/

在每个节目的文件夹内(这是问题所在),我有季节文件夹。我目前混合了以下两个约定(可能还有其他几个约定):

  1. /media/Expansion2/Series/The Big Bang Theory/The Big Bang Theory Season 1
  2. /media/Expansion2/Series/The Big Bang Theory/Season 2

最后,我想将所有文件夹重命名为just Season #

作为正则表达式,我可能会说类似 s/.*(Season \d)/$1

仅适用于文件夹,不适用于文件。我可能还应该提到,这是用于大约50多个show sub文件夹的,因此它需要从/media/Expansion2/Series/级别开始并研究每个系列:)

Answers:


12

在Debian及其衍生产品(包括Ubuntu)上:

find /media/Expansion2/Series/ -type d -exec rename -n 's/.*(Season \d)/$1/' {} ";"

rename命令是Perl软件包的一部分。它不是由其他发行版提供的,而是提供了标准的Linux rename命令,在这里没有用。

如果rename -n(-不是真的)显示了它想要做什么,并且对您来说没问题,请省略-n并使其实现。


必须说,最近几天我发现这种方法特别有用-不仅对于文件夹,而且对于文件也是如此。谢谢。
Denham Coote

1
据我所记得,该工具rename在Debian上被调用。在Ubuntu(及某些版本)上,为了避免与前面提到的标准命令发生名称冲突,有时(但并非总是)在下找到该命令。在Lubuntu上,该工具本身被称为,但由于符号链接链()的稍微修改版本,因此可以将其称为。renameprenameprenamerename/usr/bin/rename -> /etc/alternatives/rename -> /usr/bin/file-renamefile-renameprename
2014年

太棒了!这使我可以对多个目录中的多个文件执行此操作!
eusoubrasileiro

2

以下代码段剥离了在下的Season [0-9]每个show目录中最后一次出现之前发生的所有内容/media/Expansion2/Series。不必使用正则表达式,而只需使用glob。

cd /media/Expansion2/Series
for show in ./*/; do
    (
        cd "$show" || { echo "cd failed.  Skipping $show"; exit 1; }
        for season in ./*Season\ [[:digit:]]*/; do
                season_prefix=${season%Season [[:digit:]]*}
                mv "$season" ./"${season#$season_prefix}"
        done
    )
done

2

如果您更喜欢安全播放,请仅重命名some show/some show stuffsome show/stuff

for d in */; do
  for f in "$d${d%/} *"; do
    mv "$f" "${d}${f%$d${d%/} }"
  done
done

如果要剥离之前的所有内容Season

for x in */*Season*; do
  mv "$x" "${x%/*}/${x##*Season}Season"
done

${var#PATTERN}在开头删除PATTERN $var并返回结果。${var%PATTERN}最后做同样的事情。${var#PATTERN}并分别${var%PATTERN}删除最短的匹配前缀和后缀;${var##PATTERN}${var%%PATTERN}删除最长的匹配项。


0

我将再发布两个解决方案,希望它们对将来有所帮助。这些来自工作中的Linux管理员。只是显示有多少把锤子作用在这个钉子上!

解决方案1:

嗨德纳姆,

我在这里必须做一些假设,例如,带有“ XXX Season#”的目录部分将始终是“外部”目录(叶节点)。

无论如何,我都会写一个小脚本。这样的事情应该起作用(注意变量周围的双引号,以确保捕获目录中的所有空格):

find /media/Expansion2/Series/ -type d | while read olddir
do 
   newdir=`echo "${olddir}" | awk -F "/" '$NF ~ /Season/ { last=substr($NF,index($NF, "Season")); while (i<(NF-1)) { i++; printf("/%s", $i) }; printf("/%s\n", last) } $NF !~ /Season/ { print }'`
   if [ "${olddir}" != "${newdir}" ]
   then
       mv "${olddir}" "${newdir}"
   fi
done

当然,在使用命令“ mv” $ {olddir}“” $ {newdir}“”“来运行它之前,您应该输入” echo“ $ {olddir}”“ $ {newdir}”“这样的内容,以确保您得到您期望的结果,否则您可能会再次头痛:-P


解决方案2:

嗨德纳姆,

大多数答案已经在问题中了。无论如何,从Series文件夹运行类似以下内容的文件都应该可以正常工作:

find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "`dirname "$dir"`/`basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i"`"; done  


说明:
•find -mindepth 2 -maxdepth 2 -type d(列出目录向下两级)
。(在每个目录上循环)
•mv -T“ $ dir”(将源目录移动到...-如果Season文件夹不是唯一的,则错误-T是必需的,即您没有“ The Big Bang Theory Season” 22“和” Season 22“在同一目录中)
•dirname” $ dir“返回目录所在的路径
•basename” $ dir“返回目录名称
•sed” s /。Season([0-9])$ / Season \ 1 / i“以不区分大小写的正则表达式来完成魔术,以防万一。

在我的小型测试中,它可以正常工作(先在mv之前用回声尝试一下):

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/The Big Bang Theory Season 1
./The Big Bang Theory/The Big Bang Theory Season 1/file1.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file 3.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file2.avi
./The Big Bang Theory/The Big Bang Theory Season 1/file
./The Big Bang Theory/The Big Bang Theory Season 1/3.avi
./Other Series
./Other Series/Season 2
./Other Series/Stre dsfdf sd dSeason 3

someuser@linux-box:/tmp/Series$ find -mindepth 2 -maxdepth 2 -type d | while read dir; do mv -T "$dir" "dirname "$dir"/basename "$dir" | sed "s/.*Season \([0-9]*\)$/Season \1/i""; done
mv: ./The Big Bang Theory/Season 2' and./The Big Bang Theory/Season 2' are the same file
mv: ./Other Series/Season 2' and./Other Series/Season 2' are the same file

someuser@linux-box:/tmp/Series$ find
.
./The Big Bang Theory
./The Big Bang Theory/Season 2
./The Big Bang Theory/Season 2/file1.avi
./The Big Bang Theory/Season 2/file 3.avi
./The Big Bang Theory/Season 2/file2.avi
./The Big Bang Theory/Season 2/file
./The Big Bang Theory/Season 2/3.avi
./The Big Bang Theory/Season 1
./The Big Bang Theory/Season 1/file1.avi
./The Big Bang Theory/Season 1/file 3.avi
./The Big Bang Theory/Season 1/file2.avi
./The Big Bang Theory/Season 1/file
./The Big Bang Theory/Season 1/3.avi
./Other Series
./Other Series/Season 3
./Other Series/Season 2

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.