如何使用前缀/后缀重命名?


95

我该怎么办 mv original.filename new.original.filename不重新输入原始文件名?

我可以想象能够做类似的事情,mv -p=new. original.filename或者做类似的mv original.filename new.~事情,但是在查看man mv/ info mv页面后我看不到任何类似的东西。

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

Answers:


122

在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一起使用。
彼得·布顿

29
这不能使用通配符。也就是说,在包含文件名a,b,c的目录中,使用“ echo {,new。} *”会产生列表“ abc new。*”(因为通过括号扩展生成文件名是在扩展通配符之前-至少通过推断)。
乔纳森·勒夫勒

几个月以来,我一直在寻找仅使用基本Shell功能的解决方案...我永远都不会想出这么简单的东西,非常感谢!
flnk

感谢您对Brace Expansion的引用:-)正是我想要的!
Pim Hazebroek '17

1
我喜欢这个例子。我现在想在午餐时间去巴斯金·罗宾斯。
Sridhar Sarnobat

157

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

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

编辑:如果rename不可用,并且您必须重命名多个文件,则Shell脚本的确非常简单。例如,所有重命名*.jpgprefix_*.jpg当前目录:

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

这个周末安装了石墨,这实际上是一个步骤(“将所有* .example文件复制到conf文件夹中,删除示例后缀”)。他们真的很懒,但是rename 's/(.*).example/$1/' *.example从沉闷中解救了我。
Conrad.Dean 2013年

2
到目前为止,这是最好的答案。
lifeisfoo

$在这种情况下,我认为您不需要第一个。就是这样's/(.*)/new.$1/'
威斯巴基

1
rename命令在我的RHEL 6计算机上不起作用。此命令是否有其他版本?在for ... done为我工作。
robsch


10

我见过有人提到一个rename命令,但是它在Unix系统上不是常规可用的(相对于Linux系统或Cygwin,在这两个系统上,重命名都是可执行文件而不是脚本)。该版本的rename功能相当有限:

rename from to file ...

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

rename foo foo0 foo? foo??

这会将foo1重命名为foo01,并将foo10重命名为foo010,依此类推。

我使用了Perl脚本rename,该脚本最初是从第一版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'
Jonathan Leffler

如果“从”或“到”为空字符串,即要在每个文件名后附加内容或完全删除内容
怎么办

1
@Troyseph-附加'.html到文件名,使用's/$/.html/'- tmp从文件名中的所有位置删除,使用's/tmp//g'(查找tmp并替换为任何位置)。
乔纳森·莱夫勒

4

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

ls | xargs -I fileName mv fileName fileName.suffix

2

如果可以进行修改,则可以使用后缀而不是前缀。然后,您可以使用制表符补全来获取原始文件名并添加后缀。

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


我经常需要这两个,但主要是前缀-如您所说,制表符补全可以处理后缀。
彼得·布顿

1

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

结果,我得到了这样的重命名命令列表:

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

1

批量重命名文件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

1

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

我需要wav在文件扩展名之前将'_en'后缀添加到文件夹中的所有文件中。

魔术在这里: %.*

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

如果您需要处理其他文件扩展名,请检查答案。不太直观。

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.