【问题标题】:How to rename with prefix/suffix?如何使用前缀/后缀重命名?
【发布时间】:2010-09-17 12:22:11
【问题描述】:

如何在不重新输入原始文件名的情况下使用mv original.filename new.original.filename

我可以想象能够做类似mv -p=new. original.filenamemv original.filename new.~ 或其他的事情 - 但在查看man mv / info mv 页面后我看不到这样的事情。

当然,我可以编写一个 shell 脚本来执行此操作,但它没有现有的命令/标志吗?

【问题讨论】:

    标签: bash rename filenames prefix mv


    【解决方案1】:

    如果它可以修改,您可以使用后缀而不是前缀。然后你可以使用 tab-completion 来获取原始文件名并添加后缀。

    否则,这不是 mv 命令所支持的。不过,一个简单的 shell 脚本就可以应付。

    【讨论】:

    • 通常我想要两者,但主要是前缀 - 正如你所说,制表符完成可以处理后缀。
    【解决方案2】:

    您可以使用rename(1) 命令:

    rename 's/(.*)$/new.$1/' original.filename
    

    编辑:如果rename 不可用并且您必须重命名多个文件,那么shell 脚本实际上可以很简短。例如,将当前目录下的所有*.jpg重命名为prefix_*.jpg

    for filename in *.jpg; do mv "$filename" "prefix_${filename}"; done;
    

    或者,利用Dave Webb's answer 并使用大括号扩展:

    for filename in *.jpg; do mv {,prefix_}"$filename"; done;
    

    【讨论】:

    • 本周末安装了石墨,他们有一个步骤本质上是(“将所有 *.example 文件复制到 conf 文件夹中,删除示例后缀”)。他们真的很懒惰,但rename 's/(.*).example/$1/' *.example 让我摆脱了乏味。
    • 这是迄今为止最好的答案。
    • 我认为在这种情况下您不需要第一个 $。所以只需's/(.*)/new.$1/'
    • rename 命令在我的 RHEL 6 机器上不起作用。这个命令有不同的版本吗? for ... done 为我工作。
    • 对于那些寻找后缀版本的人:for filename in *.jpg; do mv "$filename" "${filename}_suffix"; done;
    【解决方案3】:

    在 Bash 和 zsh 中,您可以使用 Brace Expansion 执行此操作。这只是扩展了大括号中的项目列表。例如:

    # echo {vanilla,chocolate,strawberry}-ice-cream
    vanilla-ice-cream chocolate-ice-cream strawberry-ice-cream
    

    所以你可以按如下方式重命名:

    mv {,new.}original.filename
    

    因为这扩展为:

    mv original.filename new.original.filename
    

    【讨论】:

    • 谢谢,这看起来是最好的解决方案 - 也适用于 ksh。
    • 这不能使用通配符。也就是说,在包含文件名 a、b、c 的目录中,使用“echo {,new.}*”会生成列表“abc new.*”(因为通过大括号扩展生成文件名发生在扩展通配符之前 - 至少通过推理)。
    • 几个月以来我一直在寻找这样的解决方案,只使用基本的 shell 功能......我永远不会想出这么简单的东西,非常感谢!
    • 感谢您对 Brace Expansion 的引用 :-) 正是我想要的!
    • 我喜欢这个例子。我现在有心情在午休时间去巴斯金罗宾斯。
    【解决方案4】:

    我见过有人提到rename 命令,但它在 Unix 系统上通常不可用(与 Linux 系统或 Cygwin 相比,在这两者上,rename 是可执行文件而不是脚本) . rename 的那个版本的功能相当有限:

    rename from to file ...
    

    它将文件名的from部分替换为to,手册页中给出的示例是:

    rename foo foo0 foo? foo??
    

    这会将 foo1 重命名为 foo01,将 foo10 重命名为 foo010,等等。

    我使用一个名为rename 的 Perl 脚本,我最初是从第一版 Camel 书中挖掘出来的,大约在 1992 年,然后对其进行了扩展,以重命名文件。

    #!/bin/perl -w
    #
    # @(#)$Id: rename.pl,v 1.7 2008/02/16 07:53:08 jleffler Exp $
    #
    # Rename files using a Perl substitute or transliterate command
    
    use strict;
    use Getopt::Std;
    
    my(%opts);
    my($usage) = "Usage: $0 [-fnxV] perlexpr [filenames]\n";
    my($force) = 0;
    my($noexc) = 0;
    my($trace) = 0;
    
    die $usage unless getopts('fnxV', \%opts);
    
    if ($opts{V})
    {
        printf "%s\n", q'RENAME Version $Revision: 1.7 $ ($Date: 2008/02/16 07:53:08 $)';
        exit 0;
    }
    $force = 1 if ($opts{f});
    $noexc = 1 if ($opts{n});
    $trace = 1 if ($opts{x});
    
    my($op) = shift;
    die $usage unless defined $op;
    
    if (!@ARGV) {
        @ARGV = <STDIN>;
        chop(@ARGV);
    }
    
    for (@ARGV)
    {
        if (-e $_ || -l $_)
        {
            my($was) = $_;
            eval $op;
            die $@ if $@;
            next if ($was eq $_);
            if ($force == 0 && -f $_)
            {
                print STDERR "rename failed: $was - $_ exists\n";
            }
            else
            {
                print "+ $was --> $_\n" if $trace;
                print STDERR "rename failed: $was - $!\n"
                    unless ($noexc || rename($was, $_));
            }
        }
        else
        {
            print STDERR "$_ - $!\n";
        }
    }
    

    这允许您编写任何 Perl 替代或音译命令来映射文件名。 在请求的具体示例中,您将使用:

    rename 's/^/new./' original.filename
    

    【讨论】:

    • 谢谢,如果我能接受第二个答案,就是这样。我想要一个标准命令,它只适用于我可能使用的任何东西,但我可以将此脚本放在我经常使用的机器上,它仍然会有所帮助。
    • James Wong 指出,对于 Arch Linux,您可以通过 pacman 使用:pacman -Sy perl-rename 下载并安装此脚本。然后在 bashrc 中为其添加别名:alias rename='perl-rename'
    • 如果 "from" 或 "to" 是空字符串怎么办,即你想在每个文件名上附加一些内容或完全删除一些内容
    • @Troyseph — 将'.html 附加到文件名,使用's/$/.html/' — 从文件名中的任何位置删除tmp,使用's/tmp//g'(找到tmp 并替换为到处都没有)。
    【解决方案5】:

    您可以通过创建 for 循环来实现与 unix 兼容的多文件重命名(使用通配符):

    for file in *; do
      mv $file new.${file%%}
    done
    

    【讨论】:

    【解决方案6】:

    就我而言,我有一组文件需要重命名才能使用它们。每个文件在组中都有自己的角色,并且有自己的模式。

    结果我有一个像这样的重命名命令列表:

    f=`ls *canctn[0-9]*`   ;  mv $f  CNLC.$f
    f=`ls *acustb[0-9]*`   ;  mv $f  CATB.$f
    f=`ls *accusgtb[0-9]*` ;  mv $f  CATB.$f
    f=`ls *acus[0-9]*`     ;  mv $f  CAUS.$f
    

    也试试这个:

    f=MyFileName; mv $f {pref1,pref2}$f{suf1,suf2}
    

    这将产生所有带有前缀和后缀的组合:

    pref1.MyFileName.suf1
    ...
    pref2.MyFileName.suf2
    

    解决同样问题的另一种方法是创建映射数组并为每个文件类型添加 corespondent 前缀,如下所示:

    #!/bin/bash
    unset masks
    typeset -A masks
    masks[ip[0-9]]=ip
    masks[iaf_usg[0-9]]=ip_usg
    masks[ipusg[0-9]]=ip_usg
    ...
    for fileMask in ${!masks[*]}; 
    do  
    registryEntry="${masks[$fileMask]}";
    fileName=*${fileMask}*
    [ -e ${fileName} ] &&  mv ${fileName} ${registryEntry}.${fileName}  
    done
    

    【讨论】:

      【解决方案7】:

      批量重命名文件 bash 脚本

      #!/bin/bash
      # USAGE: cd FILESDIRECTORY; RENAMERFILEPATH/MultipleFileRenamer.sh FILENAMEPREFIX INITNUMBER
      # USAGE EXAMPLE: cd PHOTOS; /home/Desktop/MultipleFileRenamer.sh 2016_
      # VERSION: 2016.03.05.
      # COPYRIGHT: Harkály Gergő | mangoRDI (https://wwww.mangordi.com/) 
      
      # check isset INITNUMBER argument, if not, set 1 | INITNUMBER is the first number after renaming
      if [ -z "$2" ]
          then i=1;
      else
          i=$2;
      fi
      
      # counts the files to set leading zeros before number | max 1000 files
      count=$(ls -l * | wc -l)
      if [ $count -lt 10 ]
          then zeros=1;
      else
          if [ $count -lt 100 ]
              then zeros=2;
          else
              zeros=3
          fi
      fi
      
      # rename script
      for file in *
      do
          mv $file $1_$(printf %0"$zeros"d.%s ${i%.*} ${file##*.})
          let i="$i+1"
      done
      

      【讨论】:

        【解决方案8】:

        批量重命名目录中文件的最简单方法是:

        ls | xargs -I fileName mv fileName fileName.suffix
        

        【讨论】:

          【解决方案9】:

          我知道这里有很好的答案,但在添加后缀时我发现没有处理文件扩展名的参考。

          我需要在文件扩展名之前为文件夹中的所有wav 文件添加“_en”后缀。

          魔法就在这里:%.*

          for filename in *.wav; do mv $filename ${filename%.*}_en.wav; done;

          如果您需要处理不同的文件扩展名,请查看this 答案。有点不直观。

          【讨论】:

            【解决方案10】:

            我不喜欢任何其他答案。
            我的看法是你想要一个普通的 bash 解决方案。所以你去吧!

            先用 echo 试试这个,看看会发生什么!
            在对数千个文件使用命令之前测试您的命令!

            如果要添加前缀,请删除“./”
            find . -type f -exec bash -c 'echo prefix_${0#./}' {} \;

            在提出的问题中,prefix_new.,因此命令变为
            find . -type f -exec bash -c 'echo mv $0 new.${0#./}' {} \;

            如果您想在扩展名后面添加一些内容,请删除它
            find . -type f -exec bash -c 'echo ${0%.*}_suffix.${0##*.}' {} \;

            现在要使用它重命名只需将 echo 替换为 mv $0

            示例:
            find . -type f -exec bash -c 'mv $0 1.${0#./}' {} \;

            灵感来自: https://gist.github.com/larshaendler/723d2ec447c3c694b71dc6e3bc3aadc9

            【讨论】:

            • 这个答案对我很有帮助。注意:对于前缀示例,您为所有文件运行命令,并且不检查是否只有预期的文件受到影响。我的意思是,您可能想为-name 'original*' 添加额外检查,例如:find . -type f -name 'original*' -exec bash -c 'echo mv $0 new.${0#./}' {} \;
            猜你喜欢
            • 2012-08-15
            • 2015-11-19
            • 2020-10-16
            • 2017-09-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-10-19
            相关资源
            最近更新 更多