基于多种模式重命名文件的更好方法 [英] Better way to rename files based on multiple patterns

查看:18
本文介绍了基于多种模式重命名文件的更好方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我下载的很多文件的文件名中都有废话/垃圾邮件,例如

a lot of files I download have crap/spam in their filenames, e.g.

[ www.crap.com ] file.name.ext

www.crap.com - file.name.ext

我想出了两种处理它们的方法,但它们看起来都很笨拙:

I've come up with two ways for dealing with them but they both seem pretty clunky:

带参数扩展:

if [[ ${base_name} != ${base_name//[+([^]])]} ]]
then
    mv -v "${dir_name}/${base_name}" "${dir_name}/${base_name//[+([^]])]}" &&
        base_name="${base_name//[+([^]])]}"
fi

if [[ ${base_name} != ${base_name//www.*.com - /} ]]
then
    mv -v "${dir_name}/${base_name}" "${dir_name}/${base_name//www.*.com - /}" &&
        base_name="${base_name//www.*.com - /}"
fi

# more of these type of statements; one for each type of frequently-encountered pattern

然后使用 echo/sed:

and then with echo/sed:

tmp=`echo "${base_name}" | sed -e 's/[[^][]*]//g' | sed -e 's/s-s//g'`
mv "${base_name}" "{tmp}"

我觉得参数扩展是两者中最差的,但我喜欢它,因为我能够在重命名后保留分配给文件的相同变量以供进一步处理(上面的代码用于名为文件下载完成后的每个文件).

I feel like the parameter expansion is the worse of the two but I like it because I'm able to keep the same variable assigned to the file for further processing after the rename (the above code is used in a script that's called for each file after the file download is complete).

所以无论如何,我希望有一种更好/更干净的方法来执行上述操作,让比我知识渊博的人可以向我展示,最好以一种允许我轻松地将旧/原始变量重新分配给新/重命名文件的方式.

So anyway I was hoping there's a better/cleaner way to do the above that someone more knowledgeable than myself could show me, preferably in a way that would allow me to easily reassign the old/original variable to the new/renamed file.

谢谢

推荐答案

两个答案:使用 重命名或使用 pure

由于有些人不喜欢 perl,我写了我的 bash only 版本

Two answer: using perl rename or using pure bash

As there are some people who dislike perl, I wrote my bash only version

是的,这是 rename 命令的典型工作,它专门用于:

Yes, this is a typical job for rename command which was precisely designed for:

man rename | sed -ne '/example/,/^[^ ]/p'
   For example, to rename all files matching "*.bak" to strip the
   extension, you might say

           rename 's/.bak$//' *.bak

   To translate uppercase names to lower, you'd use

           rename 'y/A-Z/a-z/' *

更有针对性的样本

只需删除所有空格方括号:

rename 's/[ []]*//g;' *.ext

重命名所有.jpg,从1开始编号:

Rename all .jpg by numbering from 1:

rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg

演示:

touch {a..e}.jpg
ls -ltr
total 0
-rw-r--r-- 1 user user 0 sep  6 16:35 e.jpg
-rw-r--r-- 1 user user 0 sep  6 16:35 d.jpg
-rw-r--r-- 1 user user 0 sep  6 16:35 c.jpg
-rw-r--r-- 1 user user 0 sep  6 16:35 b.jpg
-rw-r--r-- 1 user user 0 sep  6 16:35 a.jpg
rename 's/^.*$/sprintf "IMG_%05d.JPG",++$./e' *.jpg
ls -ltr
total 0
-rw-r--r-- 1 user user 0 sep  6 16:35 IMG_00005.JPG
-rw-r--r-- 1 user user 0 sep  6 16:35 IMG_00004.JPG
-rw-r--r-- 1 user user 0 sep  6 16:35 IMG_00003.JPG
-rw-r--r-- 1 user user 0 sep  6 16:35 IMG_00002.JPG
-rw-r--r-- 1 user user 0 sep  6 16:35 IMG_00001.JPG

以安全方式匹配 SO 问题的完整语法

使用 rename 实用程序有一种强大且安全的方法:

Full syntax for matching SO question, in safe way

There is a strong and safe way using rename utility:

由于这是 常用工具,我们必须使用 perl 语法:

As this is perl common tool, we have to use perl syntax:

rename 'my $o=$_;
        s/[ []]+/-/g;
        s/-+/-/g;
        s/^-//g;
        s/-(..*|)$/$1/g;
        s/(.*[^d])(|-(d+))(.[a-z0-9]{2,6})$/
                my $i=$3;
                $i=0 unless $i;
                sprintf("%s-%d%s", $1, $i+1, $4)
            /eg while
               $o ne $_  &&
               -f $_;
    ' *

测试规则:

touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext'
ls -1
[ www.crap.com ] file.name.ext
www.crap.com - file.name.ext
rename 'my $o=$_; ...
    ...
    ...' *
ls -1
www.crap.com-file.name-1.ext
www.crap.com-file.name.ext

touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext'
ls -1
www.crap.com-file.name-1.ext
[ www.crap.com ] file.name.ext
www.crap.com - file.name.ext
www.crap.com-file.name.ext
rename 'my $o=$_; ...
    ...
    ...' *
ls -1
www.crap.com-file.name-1.ext
www.crap.com-file.name-2.ext
www.crap.com-file.name-3.ext
www.crap.com-file.name.ext

...等等...

... 并且当您不使用 -f 标志到 rename 命令时它是安全的:文件不会被覆盖,如果出现以下情况,您将收到错误消息出了点问题.

... and it's safe while you don't use -f flag to rename command: file won't be overwrited and you will get an error message if something goes wrong.

我更喜欢使用专用实用程序来完成此操作,但这甚至可以通过使用 pure (也就是没有任何叉子)

I prefer doing this by using dedicated utility, but this could even be done by using pure bash (aka without any fork)

没有使用除 bash 之外的任何其他二进制文件(没有 sedawktr 或其他):

There is no use of any other binary than bash (no sed, awk, tr or other):

#!/bin/bash

for file;do
    newname=${file//[ ][]/.}
    while [ "$newname" != "${newname#.}" ] ;do
        newname=${newname#.}
      done
    while [ "$newname" != "${newname//[.-][.-]/.}" ] ;do
        newname=${newname//[.-][.-]/-};done
    if [ "$file" != "$newname" ] ;then
        if [ -f $newname ] ;then
            ext=${newname##*.}
            basename=${newname%.$ext}
            partname=${basename%%-[0-9]}
            count=${basename#${partname}-}
            [ "$partname" = "$count" ] && count=0
            while printf -v newname "%s-%d.%s" $partname $[++count] $ext &&
                  [ -f "$newname" ] ;do
              :;done
          fi
        mv  "$file" $newname
      fi
  done

以文件为参数运行,示例:

To be run with files as argument, for sample:

/path/to/my/script.sh [*

  • 用点代替空格和方括号
  • 仅用一个 替换 .--.--.. 的序列>-.
  • 测试文件名是否相同,则无事可做.
  • 测试文件是否存在 newname...
  • 拆分文件名、计数器和扩展名,用于制作索引新名称
  • 循环,如果一个文件存在 newname
  • 最后重命名文件.
    • Replacing spaces and square bracket by dot
    • Replacing sequences of .-, -., -- or .. by only one -.
    • Test if filename don't differ, there is nothing to do.
    • Test if a file exist with newname...
    • split filename, counter and extension, for making indexed newname
    • loop if a file exist with newname
    • Finaly rename the file.
    • 这篇关于基于多种模式重命名文件的更好方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆