基于多种模式重命名文件的更好方法

时间:2021-07-15 01:13:31

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

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:

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

with parameter expansion:

参数扩展:

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

and then with echo/sed:

然后使用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.

所以无论如何我希望有一个更好/更清洁的方法来做上述事情,比我自己更有知识的人可以告诉我,最好以一种允许我轻松地将旧/原始变量重新分配给新/重命名文件的方式。

Thanks

谢谢

5 个解决方案

#1


7  

Two answer: using rename or using pure

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

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

Renaming files by using the rename command.

Introduction

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/' *

More oriented samples

Simply drop all spaces and square brackets:

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

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

Rename all .jpg by numbering from 1:

通过编号从1重命名所有.jpg:

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

Demo:

演示:

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

Full syntax for matching SO question, in safe way

There is a strong and safe way using rename utility:

使用重命名实用程序有一种强大而安全的方法:

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

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

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 $_;
    ' *

Testing rule:

测试规则:

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

... and so on...

... 等等...

... 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.

...并且在您不使用-f标志重命名命令时它是安全的:文件不会被覆盖,如果出现问题,您将收到错误消息。

Renaming files by using and so called bashisms:

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

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

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

除了bash(没有sed,awk,tr或其他)之外,没有使用任何其他二进制文件:

#!/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 \[*
  • 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...
  • 测试文件是否存在newname ...
  • split filename, counter and extension, for making indexed newname
  • 拆分文件名,计数器和扩展名,用于制作索引的新名称
  • loop if a file exist with newname
  • 如果文件存在newname则循环
  • Finaly rename the file.
  • 最终重命名该文件。

#2


6  

Take advantage of the following classical pattern:

利用以下经典模式:

 job_select /path/to/directory| job_strategy | job_process

where job_select is responsible for selecting the objects of your job, job_strategy prepares a processing plan for these objects and job_process eventually executes the plan.

job_select负责选择作业对象,job_strategy为这些对象准备处理计划,job_process最终执行计划。

This assumes that filenames do not contain a vertical bar | nor a newline character.

这假设文件名不包含竖线条也不是换行符。

The job_select function

job_select功能

 # job_select PATH
 #  Produce the list of files to process
 job_select()
 {
   find "$1" -name 'www.*.com - *' -o -name '[*] - *'
 }

The find command can examine all properties of the file maintained by the file system, like creation time, access time, modification time. It is also possible to control how the filesystem is explored by telling find not to descend into mounted filesystems, how much recursions levels are allowed. It is common to append pipes to the find command to perform more complicated selections based on the filename.

find命令可以检查文件系统维护的文件的所有属性,如创建时间,访问时间,修改时间。通过告诉find不要下载到已挂载的文件系统,允许多少递归级别,也可以控制文件系统的探索方式。通常将管道附加到find命令以基于文件名执行更复杂的选择。

Avoid the common pitfall of including the contents of hidden directories in the output of the job_select function. For instance, the directories CVS, .svn, .svk and .git are used by the corresponding source control management tools and it is almost always wrong to include their contents in the output of the job_select function. By inadvertently batch processing these files, one can easily make the affected working copy unusable.

避免在job_select函数的输出中包含隐藏目录的内容的常见缺陷。例如,目录CVS,.svn,.svk和.git由相应的源代码管理工具使用,将其内容包含在job_select函数的输出中几乎总是错误的。通过无意中批处理这些文件,可以轻松地使受影响的工作副本无法使用。

The job_strategy function

job_strategy函数

# job_strategy
#  Prepare a plan for renaming files
job_strategy()
{
  sed -e '
    h
    s@/www\..*\.com - *@/@
    s@/\[^]]* - *@/@
    x
    G
    s/\n/|/
  '
}

This commands reads the output of job_select and makes a plan for our renaming job. The plan is represented by text lines having two fields separated by the character |, the first field being the old name of the file and the second being the new computed file of the file, it looks like

此命令读取job_select的输出并为重命名作业制定计划。该计划由文本行表示,其中两个字段由字符|分隔,第一个字段是文件的旧名称,第二个字段是文件的新计算文件,它看起来像

[ www.crap.com ] file.name.1.ext|file.name.1.ext
www.crap.com - file.name.2.ext|file.name.2.ext

The particular program used to produce the plan is essentially irrelevant, but it is common to use sed as in the example; awk or perl for this. Let us walk through the sed-script used here:

用于制定计划的特定程序基本上是无关紧要的,但在示例中使用sed是很常见的; awk或perl为此。让我们来看看这里使用的sed脚本:

h       Replace the contents of the hold space with the contents of the pattern space.
…       Edit the contents of the pattern space.
x       Swap the contents of the pattern and hold spaces.
G       Append a newline character followed by the contents of the hold space to the pattern space.
s/\n/|/ Replace the newline character in the pattern space by a vertical bar.

It can be easier to use several filters to prepare the plan. Another common case is the use of the stat command to add creation times to file names.

使用多个过滤器来准备计划可能更容易。另一种常见情况是使用stat命令将创建时间添加到文件名。

The job_process function

job_process函数

# job_process
#  Rename files according to a plan
job_process()
{
   local oldname
   local newname
   while IFS='|' read oldname newname; do
     mv "$oldname" "$newname"
   done
}

The input field separator IFS is adjusted to let the function read the output of job_strategy. Declaring oldname and newname as local is useful in large programs but can be omitted in very simple scripts. The job_process function can be adjusted to avoid overwriting existing files and report the problematic items.

调整输入字段分隔符IFS以使该函数读取job_strategy的输出。将oldname和newname声明为local在大型程序中很有用,但在非常简单的脚本中可以省略。可以调整job_process函数以避免覆盖现有文件并报告有问题的项目。

About data structures in shell programs Note the use of pipes to transfer data from one stage to the other: apprentices often rely on variables to represent such information but it turns out to be a clumsy choice. Instead, it is preferable to represent data as tabular files or as tabular data streams moving from one process to the other, in this form, data can be easily processed by powerful tools like sed, awk, join, paste and sort — only to cite the most common ones.

关于shell程序中的数据结构注意使用管道将数据从一个阶段传输到另一个阶段:学徒通常依靠变量来表示这些信息,但事实证明这是一个笨拙的选择。相反,最好将数据表示为表格文件或表格数据流从一个进程移动到另一个进程,在这种形式下,数据可以通过强大的工具(如sed,awk,join,paste和sort)轻松处理 - 仅用于引用最常见的。

#3


0  

If you are using Ubunntu/Debian os use rename command to rename multiple files at time.

如果您正在使用Ubunntu / Debian,请使用rename命令重命名多个文件。

#4


0  

If you want to use something not depending on perl, you can use the following code (let's call it sanitizeNames.sh). It is only showing a few cases, but it's easily extensible using string substitution, tr (and sed too).

如果你想使用不依赖于perl的东西,可以使用下面的代码(让我们称之为sanitizeNames.sh)。它只显示了一些情况,但它很容易使用字符串替换tr(和sed)进行扩展。

    #!/bin/bash

    ls $1 |while read f; do
      newfname=$(echo "$f" \
                  |tr -d '\[ ' \    # Removing opened square bracket
                  |tr ' \]' '-' \   # Translating closing square bracket to dash
                  |tr -s '-' \      # Squeezing multiple dashes
                  |tr -s '.' \      # Squeezing multiple dots
                )
      newfname=${newfname//-./.}

      if [ -f "$newfname" ]; then
        # Some string magic...
        extension=${newfname##*\.}
        basename=${newfname%\.*}
        basename=${basename%\-[1-9]*}
        lastNum=$[ $(ls $basename*|wc -l) ] 
        mv "$f" "$basename-$lastNum.$extension"
      else
        mv "$f" "$newfname"
      fi
    done

And use it:

并使用它:

    $ touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext' '[ www.crap.com ] - file.name.ext' '[www.crap.com ].file.anothername.ext2' '[www.crap.com ].file.name.ext'
    $ ls -1 *crap*
    [ www.crap.com ] - file.name.ext
    [ www.crap.com ] file.name.ext
    [www.crap.com ].file.anothername.ext2
    [www.crap.com ].file.name.ext
    www.crap.com - file.name.ext
    $ ./sanitizeNames.sh *crap*
    $ ls -1 *crap*
    www.crap.com-file.anothername.ext2
    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

#5


0  

You can use rnm

你可以使用rnm

rnm -rs '/\[crap\]|\[spam\]//g' *.ext

The above will remove [crap] or [spam] from filename.

以上将从文件名中删除[crap]或[spam]。

You can pass multiple regex pattern by terminating them with ; or overloading the -rs option.

您可以通过终止它们来传递多个正则表达式模式;或重载-rs选项。

rnm -rs '/[\[\]]//g;/\s*\[crap\]//g' -rs '/crap2//' *.ext

The general format of this replace string is /search_part/replace_part/modifier

此替换字符串的一般格式是/ search_part / replace_part / modifier

  1. search_part : regex to search for.
  2. search_part:要搜索的正则表达式。
  3. replace_part : string to replace with
  4. replace_part:要替换的字符串
  5. modifier : i (case insensitive), g (global replace)
  6. 修饰符:i(不区分大小写),g(全局替换)

uppercase/lowercase:

大写小写:

A replace string of the form /search_part/\c/modifier will make the selected part of the filename (by the regex search_part) lowercase while \C (capital \C) in replace part will make it uppercase.

/ search_part / \ c / modifier形式的替换字符串将使文件名的选定部分(通过正则表达式search_part)为小写,而替换部分中的\ C(capital \ C)将使其为大写。

rnm -rs '/[abcd]/\C/g' *.ext
## this will capitalize all a,b,c,d in the filenames


If you have many regex patterns that need to be dealt with, then put those patterns in a file and pass the file with -rs/f option.

rnm -rs/f /path/to/regex/pattern/file *.ext

You can find some other examples here.

你可以在这里找到一些其他的例子。

Note:

注意:

  1. rnm uses PCRE2 (revised PCRE) regex.
  2. rnm使用PCRE2(修订后的PCRE)正则表达式。
  3. You can undo an unwanted rename operation by running rnm -u
  4. 您可以通过运行rnm -u撤消不需要的重命名操作

P.S: I am the author of this tool.

P.S:我是这个工具的作者。

#1


7  

Two answer: using rename or using pure

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

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

Renaming files by using the rename command.

Introduction

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/' *

More oriented samples

Simply drop all spaces and square brackets:

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

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

Rename all .jpg by numbering from 1:

通过编号从1重命名所有.jpg:

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

Demo:

演示:

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

Full syntax for matching SO question, in safe way

There is a strong and safe way using rename utility:

使用重命名实用程序有一种强大而安全的方法:

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

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

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 $_;
    ' *

Testing rule:

测试规则:

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

... and so on...

... 等等...

... 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.

...并且在您不使用-f标志重命名命令时它是安全的:文件不会被覆盖,如果出现问题,您将收到错误消息。

Renaming files by using and so called bashisms:

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

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

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

除了bash(没有sed,awk,tr或其他)之外,没有使用任何其他二进制文件:

#!/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 \[*
  • 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...
  • 测试文件是否存在newname ...
  • split filename, counter and extension, for making indexed newname
  • 拆分文件名,计数器和扩展名,用于制作索引的新名称
  • loop if a file exist with newname
  • 如果文件存在newname则循环
  • Finaly rename the file.
  • 最终重命名该文件。

#2


6  

Take advantage of the following classical pattern:

利用以下经典模式:

 job_select /path/to/directory| job_strategy | job_process

where job_select is responsible for selecting the objects of your job, job_strategy prepares a processing plan for these objects and job_process eventually executes the plan.

job_select负责选择作业对象,job_strategy为这些对象准备处理计划,job_process最终执行计划。

This assumes that filenames do not contain a vertical bar | nor a newline character.

这假设文件名不包含竖线条也不是换行符。

The job_select function

job_select功能

 # job_select PATH
 #  Produce the list of files to process
 job_select()
 {
   find "$1" -name 'www.*.com - *' -o -name '[*] - *'
 }

The find command can examine all properties of the file maintained by the file system, like creation time, access time, modification time. It is also possible to control how the filesystem is explored by telling find not to descend into mounted filesystems, how much recursions levels are allowed. It is common to append pipes to the find command to perform more complicated selections based on the filename.

find命令可以检查文件系统维护的文件的所有属性,如创建时间,访问时间,修改时间。通过告诉find不要下载到已挂载的文件系统,允许多少递归级别,也可以控制文件系统的探索方式。通常将管道附加到find命令以基于文件名执行更复杂的选择。

Avoid the common pitfall of including the contents of hidden directories in the output of the job_select function. For instance, the directories CVS, .svn, .svk and .git are used by the corresponding source control management tools and it is almost always wrong to include their contents in the output of the job_select function. By inadvertently batch processing these files, one can easily make the affected working copy unusable.

避免在job_select函数的输出中包含隐藏目录的内容的常见缺陷。例如,目录CVS,.svn,.svk和.git由相应的源代码管理工具使用,将其内容包含在job_select函数的输出中几乎总是错误的。通过无意中批处理这些文件,可以轻松地使受影响的工作副本无法使用。

The job_strategy function

job_strategy函数

# job_strategy
#  Prepare a plan for renaming files
job_strategy()
{
  sed -e '
    h
    s@/www\..*\.com - *@/@
    s@/\[^]]* - *@/@
    x
    G
    s/\n/|/
  '
}

This commands reads the output of job_select and makes a plan for our renaming job. The plan is represented by text lines having two fields separated by the character |, the first field being the old name of the file and the second being the new computed file of the file, it looks like

此命令读取job_select的输出并为重命名作业制定计划。该计划由文本行表示,其中两个字段由字符|分隔,第一个字段是文件的旧名称,第二个字段是文件的新计算文件,它看起来像

[ www.crap.com ] file.name.1.ext|file.name.1.ext
www.crap.com - file.name.2.ext|file.name.2.ext

The particular program used to produce the plan is essentially irrelevant, but it is common to use sed as in the example; awk or perl for this. Let us walk through the sed-script used here:

用于制定计划的特定程序基本上是无关紧要的,但在示例中使用sed是很常见的; awk或perl为此。让我们来看看这里使用的sed脚本:

h       Replace the contents of the hold space with the contents of the pattern space.
…       Edit the contents of the pattern space.
x       Swap the contents of the pattern and hold spaces.
G       Append a newline character followed by the contents of the hold space to the pattern space.
s/\n/|/ Replace the newline character in the pattern space by a vertical bar.

It can be easier to use several filters to prepare the plan. Another common case is the use of the stat command to add creation times to file names.

使用多个过滤器来准备计划可能更容易。另一种常见情况是使用stat命令将创建时间添加到文件名。

The job_process function

job_process函数

# job_process
#  Rename files according to a plan
job_process()
{
   local oldname
   local newname
   while IFS='|' read oldname newname; do
     mv "$oldname" "$newname"
   done
}

The input field separator IFS is adjusted to let the function read the output of job_strategy. Declaring oldname and newname as local is useful in large programs but can be omitted in very simple scripts. The job_process function can be adjusted to avoid overwriting existing files and report the problematic items.

调整输入字段分隔符IFS以使该函数读取job_strategy的输出。将oldname和newname声明为local在大型程序中很有用,但在非常简单的脚本中可以省略。可以调整job_process函数以避免覆盖现有文件并报告有问题的项目。

About data structures in shell programs Note the use of pipes to transfer data from one stage to the other: apprentices often rely on variables to represent such information but it turns out to be a clumsy choice. Instead, it is preferable to represent data as tabular files or as tabular data streams moving from one process to the other, in this form, data can be easily processed by powerful tools like sed, awk, join, paste and sort — only to cite the most common ones.

关于shell程序中的数据结构注意使用管道将数据从一个阶段传输到另一个阶段:学徒通常依靠变量来表示这些信息,但事实证明这是一个笨拙的选择。相反,最好将数据表示为表格文件或表格数据流从一个进程移动到另一个进程,在这种形式下,数据可以通过强大的工具(如sed,awk,join,paste和sort)轻松处理 - 仅用于引用最常见的。

#3


0  

If you are using Ubunntu/Debian os use rename command to rename multiple files at time.

如果您正在使用Ubunntu / Debian,请使用rename命令重命名多个文件。

#4


0  

If you want to use something not depending on perl, you can use the following code (let's call it sanitizeNames.sh). It is only showing a few cases, but it's easily extensible using string substitution, tr (and sed too).

如果你想使用不依赖于perl的东西,可以使用下面的代码(让我们称之为sanitizeNames.sh)。它只显示了一些情况,但它很容易使用字符串替换tr(和sed)进行扩展。

    #!/bin/bash

    ls $1 |while read f; do
      newfname=$(echo "$f" \
                  |tr -d '\[ ' \    # Removing opened square bracket
                  |tr ' \]' '-' \   # Translating closing square bracket to dash
                  |tr -s '-' \      # Squeezing multiple dashes
                  |tr -s '.' \      # Squeezing multiple dots
                )
      newfname=${newfname//-./.}

      if [ -f "$newfname" ]; then
        # Some string magic...
        extension=${newfname##*\.}
        basename=${newfname%\.*}
        basename=${basename%\-[1-9]*}
        lastNum=$[ $(ls $basename*|wc -l) ] 
        mv "$f" "$basename-$lastNum.$extension"
      else
        mv "$f" "$newfname"
      fi
    done

And use it:

并使用它:

    $ touch '[ www.crap.com ] file.name.ext' 'www.crap.com - file.name.ext' '[ www.crap.com ] - file.name.ext' '[www.crap.com ].file.anothername.ext2' '[www.crap.com ].file.name.ext'
    $ ls -1 *crap*
    [ www.crap.com ] - file.name.ext
    [ www.crap.com ] file.name.ext
    [www.crap.com ].file.anothername.ext2
    [www.crap.com ].file.name.ext
    www.crap.com - file.name.ext
    $ ./sanitizeNames.sh *crap*
    $ ls -1 *crap*
    www.crap.com-file.anothername.ext2
    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

#5


0  

You can use rnm

你可以使用rnm

rnm -rs '/\[crap\]|\[spam\]//g' *.ext

The above will remove [crap] or [spam] from filename.

以上将从文件名中删除[crap]或[spam]。

You can pass multiple regex pattern by terminating them with ; or overloading the -rs option.

您可以通过终止它们来传递多个正则表达式模式;或重载-rs选项。

rnm -rs '/[\[\]]//g;/\s*\[crap\]//g' -rs '/crap2//' *.ext

The general format of this replace string is /search_part/replace_part/modifier

此替换字符串的一般格式是/ search_part / replace_part / modifier

  1. search_part : regex to search for.
  2. search_part:要搜索的正则表达式。
  3. replace_part : string to replace with
  4. replace_part:要替换的字符串
  5. modifier : i (case insensitive), g (global replace)
  6. 修饰符:i(不区分大小写),g(全局替换)

uppercase/lowercase:

大写小写:

A replace string of the form /search_part/\c/modifier will make the selected part of the filename (by the regex search_part) lowercase while \C (capital \C) in replace part will make it uppercase.

/ search_part / \ c / modifier形式的替换字符串将使文件名的选定部分(通过正则表达式search_part)为小写,而替换部分中的\ C(capital \ C)将使其为大写。

rnm -rs '/[abcd]/\C/g' *.ext
## this will capitalize all a,b,c,d in the filenames


If you have many regex patterns that need to be dealt with, then put those patterns in a file and pass the file with -rs/f option.

rnm -rs/f /path/to/regex/pattern/file *.ext

You can find some other examples here.

你可以在这里找到一些其他的例子。

Note:

注意:

  1. rnm uses PCRE2 (revised PCRE) regex.
  2. rnm使用PCRE2(修订后的PCRE)正则表达式。
  3. You can undo an unwanted rename operation by running rnm -u
  4. 您可以通过运行rnm -u撤消不需要的重命名操作

P.S: I am the author of this tool.

P.S:我是这个工具的作者。