Linux:重命名文件但保留扩展名?


10

在Windows / DOS中,我可以说rename myfile.* yourfile.*要更改名称但保留扩展名。在Linux上如何完成?

手册页仅建议如何更改扩展名,但这与我想要的相反。

奖励:
实际上,我想将照片的创建日期放入文件名中,以获得类似的信息20091231 2359 New Year.jpg。恐怕我需要一些平凡的命令组合才能实现这一目标?

Answers:


14

这是奖金问题的答案。

我实际上想将照片的创建日期放入文件名中,以获得类似20091231 2359 New Year.jpg的名称。恐怕我需要一些平凡的命令组合才能实现这一目标?

假设您要从EXIF数据中获取照片的创建日期,则需要一个单独的工具。幸运的是,事实证明jhead,通过它的-n选项,它提供了一种简单的方法来精确地完成您想要的事情。

$ jhead -h
 [...]

 -n[format-string]

             Rename files according to date.  Uses exif date if present, file
             date otherwise.  If the optional format-string is not supplied,
             the format is mmdd-hhmmss.  If a format-string is given, it is
             is passed to the 'strftime' function for formatting
             In addition to strftime format codes:
             '%f' as part of the string will include the original file name
             [...]

这是一个例子:

$ jhead -n%Y-%m-%d-%f New_year.jpg   
New_year.jpg --> 2009-12-31-New_year.jpg

编辑:当然,要对一堆照片执行此操作,将类似于:

$ for i in *jpg; do jhead -n%Y-%m-%d-%f $i; done

要根据自己的喜好调整日期格式,请查看的输出date --help,例如;它将列出可用的格式代码。

(jhead可在不同的系统上广泛使用。如果例如在Ubuntu或Debian上,只需键入sudo apt-get install jhead以安装它即可。)


1
我没有想到jhead,只是想到了重命名,stat和cut的丑陋组合。感谢您的好评!
Torben Gundtofte-Bruun

10

对于重命名部分,“重命名”程序将起作用。它与您在手册页中看到的示例相同,只是切换了一下。

justin@eee:/tmp/q$ touch myfile.{a,b,c,d}
justin@eee:/tmp/q$ ls
myfile.a  myfile.b  myfile.c  myfile.d
justin@eee:/tmp/q$ rename -v s/myfile/yourfile/ myfile.*
myfile.a renamed as yourfile.a
myfile.b renamed as yourfile.b
myfile.c renamed as yourfile.c
myfile.d renamed as yourfile.d
justin@eee:/tmp/q$ ls
yourfile.a  yourfile.b  yourfile.c  yourfile.d
justin@eee:/tmp/q$ 

1
在某些发行版中,此perl重命名程序称为prename。
camh 2010年

这真的很有用!我对找到“重命名”之前必须搜索多少种这类问题感到惊讶。谢谢。
alanning

7
betelgeuse:tmp james$ ls myfile.* yourfile.*
ls: yourfile.*: No such file or directory   
myfile.a    myfile.b
betelgeuse:tmp james$ for file
> in myfile.*
> do
> mv "${file}" "`echo $file | sed 's/myfile\./yourfile./'`"
> done
betelgeuse:tmp james$ ls myfile.* yourfile.*
ls: myfile.*: No such file or directory
yourfile.a  yourfile.b

关键是,如果您看到了一个示例,该示例显示了如何使用正则表达式来修改文件名的一部分,那这就是您唯一需要的示例。扩展在UNIX文件系统上没有特殊的状态-它们只是文件名的一部分,恰好在.字符之后。


1
这是我的问题的答案。(但是另一个答案使我更快,更轻松地到达那里。)
Torben Gundtofte-Bruun

4
无需叉+ EXEC sed的:mv "$file" yourfile"${file#myfile}"。可在任何现代的Bourne式外壳(或任何POSIX外壳)上运行,但可能不适用于实际的Bourne外壳。
克里斯·约翰森

4

这是操纵文件名的几种其他方法

for f in *.jpg
do
    mv "$f" "before_part${f%.*}after_part.${f##*.}"
    # OR mv "$f" "before_part$(basename "$f" ".jpg")after_part.jpg"
done

参数扩展mv命令如下工作:

${f%.*}-从中包含的字符串的末尾删除最短的匹配模式$f,在这种情况下,删除最后一个点之后(包括最后一个点)的所有内容。单一的%意思是“从头到尾最短”。

${f##*.}-从中包含的字符串的开头删除最长的匹配模式$f,在这种情况下,最后一个点之前(包括最后一个点)(包括所有其他点)也将全部删除。双###)表示“从头开始最长”。

因此,例如,如果$f包含“ Foo.bar.baZ.jpg”:

echo "${f%.*}"

Foo.bar.baZ

echo "${f##*.}"

jpg

因此mv,一旦展开,该命令将如下所示:

mv "Foo.bar.baZ.jpg" "before_partFoo.bar.baZafter_part.jpg"

我实际上最终使用了FOR循环,但没有使用MV示例,因为我不理解它:-)
Torben Gundtofte-Bruun 2010年

注:这些的意义f%f##在这里描述,例如:tldp.org/LDP/abs/html/parameter-substitution.html
托本Gundtofte -布鲁恩

3

Linux中没有文件扩展名。

使用正则表达式从文件名中剪切特定的子字符串并进行访问。

例:

实际场景:您正在从chm文件中提取html。Windows中的文件名不区分大小写,因此在Linux中,链接会断开。您有一个名为index.HTML的文件,但URL中的href =“ index.html”。因此,您的目标是调整文件名以使其匹配链接。

假设文件名包含在变量中:

FILENAME='index.HTML'

从3.0版开始,bash本身支持正则表达式,因此您不需要任何其他工具(例如grep / sed / perl等)即可执行字符串操作。以下示例说明了字符串中后端匹配的替换:

echo ${FILENAME/%\.HTML/.html}

匹配和替换字符串可以根据需要设置参数,这在编写脚本时提供了更大的灵活性。以下代码段实现了相同的目标:

match='\.HTML'
replacement='.html'
echo ${FILENAME/%$match/$replacement}

请查阅bash文档以获取更多信息。


1
在这些正则表达式上有任何示例吗?
Gnoupi 2010年

+1。这个答案现在(在编辑之后)非常有用–我不知道您可以在Bash中进行这样的字符串操作。
Jonik 2010年

确实,现在有了例子,情况要好得多。+1
Gnoupi 2010年


0

总是有不止一种方法来做到这一点。我将以下脚本命名为/ usr / local / bin / mrename。

然后在包含照片文件的脚本中,键入:mrename

脚本中还有一个可选的注释掉功能,用于缩放照片(使用ImageMagick)。

希望这对某些人有用。

#!/usr/bin/perl
#
# mrename files
#
#
use strict;

# if no 2 args, use defaults
my $dir = ".";

# read in path from command line
$dir = $ARGV[0] if ( defined( $ARGV[0] ) && $ARGV[0] ne "" );

# read in directory contents
opendir( DIR, $dir );
my @files = readdir( DIR );
closedir( DIR );

# rename and/or scale each file in directory
my $number_of_files = scalar( @files );
my $curfile = 0;

foreach my $file( @files ) {
    # only rename and scale jpg/gif files
    if ( $file =~ /\w+\.(jpg)$/ ) {
        my $extension = $1;
        $extension =~ tr/A-Z/a-z/;
        my $full_filename = "$dir/$file";

        # get stats on file- specifically the last modified time
        (my $dev,my $ino,my $mode,my $nlink,my $uid,my $gid,my $rdev,my $size,
        my $atime,my $mtime,my $ctime,my $blksize,my $blocks) = stat($full_filename);

        # convert last-modified time from seconds to practical datetime terms
        (my $sec,my $min,my $hour,my $mday,my $mon,my $year,my $wday,my $yday,
        my $isdst) = localtime($mtime);

        ++$mon;
        $year += 1900;

        my $filecdate = sprintf( "m%04i%02i%02i_%02i%02i%02i.$extension", $year, $mon, $mday, $hour, $min, $sec );
        my $full_newfilename = "$dir/$filecdate";

        # to scale files, use imagemagick by using the command below instead of mv 
        #my $cmd = "convert $full_filename -resize $scale% $full_newfilename";
        my $cmd = "mv $full_filename $full_newfilename";
        system( $cmd );

        # update percentage done
        my $percent_done = sprintf( "%5.2lf", 100* (++$curfile) / $number_of_files );
        print "\r$percent_done%";
    }
}
print "\n";

0

您可以将-X/--keep-extension选项与rename(版本1.600)一起使用:

-X, --keep-extension Save and remove the last extension from a filename, if there is any. The saved extension will be appended back to the filename at the end of the rest of the operations.

rename 适用于Homebrew的Mac和Linuxbrew的Linux(当然还有其他安装选项)。

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.