基于查找批量重命名文件

时间:2010-11-10 02:05:37

标签: python perl bash

我有一个包含图像文件的文件夹,例如

  • 1500000704_full.jpg
  • 1500000705_full.jpg
  • 1500000711_full.jpg
  • 1500000712_full.jpg
  • 1500000714_full.jpg
  • 1500000744_full.jpg
  • 1500000745_full.jpg
  • 1500000802_full.jpg
  • 1500000803_full.jpg

我需要根据文本文件中的查找重命名文件,文本文件包含

等条目
  • SH103239 1500000704
  • SH103240 1500000705
  • SH103241 1500000711
  • SH103242 1500000712
  • SH103243 1500000714
  • SH103244 1500000744
  • SH103245 1500000745
  • SH103252 1500000802
  • SH103253 1500000803
  • SH103254 1500000804

所以,我希望重命名图像文件,

  • SH103239_full.jpg
  • SH103240_full.jpg
  • SH103241_full.jpg
  • SH103242_full.jpg
  • SH103243_full.jpg
  • SH103244_full.jpg
  • SH103245_full.jpg
  • SH103252_full.jpg
  • SH103253_full.jpg
  • SH103254_full.jpg

我怎样才能最轻松地完成这项工作?任何人都可以给我写一个快速命令或脚本,可以为我做这个吗?我有很多这些图像文件和手动更改是不可行的。

我在ubuntu上但是根据工具我可以根据需要切换到Windows。理想情况下,我希望在bash脚本中使用它,以便我可以学习更多或简单的perl或python。

由于

编辑:必须更改文件名

9 个答案:

答案 0 :(得分:7)

这是一个简单的Python 2脚本来进行重命名。

#!/usr/bin/env python

import os

# A dict with keys being the old filenames and values being the new filenames
mapping = {}

# Read through the mapping file line-by-line and populate 'mapping'
with open('mapping.txt') as mapping_file:
    for line in mapping_file:
        # Split the line along whitespace
        # Note: this fails if your filenames have whitespace
        new_name, old_name = line.split()
        mapping[old_name] = new_name

suffix = '_full'

# List the files in the current directory
for filename in os.listdir('.'):
    root, extension = os.path.splitext(filename)
    if not root.endswith(suffix):
        # File doesn't end with this suffix; ignore it
        continue
    # Strip off the number of characters that make up suffix
    stripped_root = root[:-len(suffix)]
    if stripped_root in mapping:
        os.rename(filename, ''.join(mapping[stripped_root] + suffix + extension))

脚本的各个部分都是硬编码的,实际上不应该这样。这些包括映射文件的名称(mapping.txt)和文件名后缀(_full)。这些可以作为参数传递,并使用sys.argv进行解释。

答案 1 :(得分:5)

这适用于您的问题:

#!/usr/bin/perl
while (<DATA>) {
    my($new, $old) = split;
    rename("$old.jpg", "$new.jpg")
        || die "can't rename "$old.jpg", "$new.jpg": $!";
}
__END__
SH103239 1500000704
SH103240 1500000705
SH103241 1500000711
SH103242 1500000712
SH103243 1500000714
SH103244 1500000744
SH103245 1500000745
SH103252 1500000802
SH103253 1500000803
SH103254 1500000804

ARGV切换到DATA以读取特定输入文件中的行。

通常对于大规模重命名操作,我使用更像这样的东西:

#!/usr/bin/perl
# rename script by Larry Wall
#
# eg:
#      rename 's/\.orig$//'  *.orig
#      rename 'y/A-Z/a-z/ unless /^Make/'  *
#      rename '$_ .= ".bad"'  *.f
#      rename 'print "$_: "; s/foo/bar/ if <STDIN> =~ /^y/i'  *
#      find /tmp -name '*~' -print | rename 's/^(.+)~$/.#$1/'

($op = shift) || die "Usage: rename expr [files]\n";

chomp(@ARGV = <STDIN>) unless @ARGV;

for (@ARGV) {
    $was = $_;
    eval $op;
    die if $@;  # means eval `failed'
    rename($was,$_) unless $was eq $_;
}

我有一个功能更全面的版本,但这应该足够了。

答案 2 :(得分:2)

重写Wesley使用生成器:

import os, os.path

with open('mapping.txt') as mapping_file:
    mapping = dict(line.strip().split() for line in mapping_file)

rootextiter = ((filename, os.path.splitext(filename)) for filename in os.listdir('.'))
mappediter = (
    (filename, os.path.join(mapping[root], extension))
    for filename, root, extension in rootextiter
    if root in mapping
)
for oldname, newname in mappediter:
    os.rename(oldname, newname)

答案 3 :(得分:2)

这在Bash中非常简单,假设每个文件的查找文件中都有一个条目,并且每个文件都有一个查找条目。

#!/bin/bash
while read -r to from
do
    if [ -e "${from}_full.jpg" ]
    then
        mv "${from}_full.jpg" "${to}_full.jpg"
    fi
done < lookupfile.txt

如果查找文件的条目多于文件,那么这种方法可能效率低下。如果相反,则迭代文件的方法可能效率低下。但是,如果数字接近,那么这可能是最好的方法,因为它不必实际进行任何查找。

如果您更喜欢纯粹Bash的查找版本:

#!/bin/bash
while read -r to from
do
    lookup[from]=$to
done < lookupfile.txt

for file in *.jpg
do
    base=${file%*_full.jpg}
    mv "$file" "${lookup[base]}_full.jpg"
done

答案 4 :(得分:2)

我修改了Wesley的代码以适应我的具体情况。我有一个映射文件“sort.txt”,它由不同的.pdf文件和数字组成,以根据网站DOM操作的输出指示我想要它们的顺序。我想将所有这些单独的pdf文件合并到一个pdf文件中,但我想保留它们在网站上的相同顺序。所以我想根据导航菜单中的树位置添加数字。

1054 spellchecking.pdf
1055 using-macros-in-the-editor.pdf
1056 binding-macros-with-keyboard-shortcuts.pdf
1057 editing-macros.pdf
1058 etc........

以下是我提出的代码:

import os, sys

# A dict with keys being the old filenames and values being the new filenames
mapping = {}

# Read through the mapping file line-by-line and populate 'mapping'
with open('sort.txt') as mapping_file:
    for line in mapping_file:

        # Split the line along whitespace
        # Note: this fails if your filenames have whitespace
        new_name, old_name = line.split()
        mapping[old_name] = new_name


# List the files in the current directory
for filename in os.listdir('.'):
    root, extension = os.path.splitext(filename)

    #rename, put number first to allow for sorting by name and 
    #then append original filename +e extension
    if filename in mapping:
        print "yay" #to make coding fun
        os.rename(filename, mapping[filename] + filename + extension)

我没有像_full这样的后缀,所以我不需要那个代码。除了相同的代码,我从来没有真正触及过python,所以这对我来说是一次很好的学习经历。

答案 5 :(得分:1)

读入文本文件,使用当前文件名创建哈希,以便files['1500000704'] = 'SH103239'等等。然后浏览当前目录中的文件,从哈希中获取新文件名,并重命名。

答案 6 :(得分:1)

#!/bin/bash

for FILE in *.jpg; do
    OLD=${FILE%.*}  # Strip off extension.
    NEW=$(awk -v "OLD=$OLD" '$2==OLD {print $1}' map.txt)
    mv "$OLD.jpg" "$NEW.jpg"
done

答案 7 :(得分:0)

这是一个有趣的小黑客:

paste -d " " lookupfile.txt lookupfile.txt | cut -d " " -f 2,3 | sed "s/\([ ]\|$\)/_full.jpg /g;s/^/mv /" | sh

答案 8 :(得分:0)

import os,re,sys

mapping = <Insert your mapping here> #Dictionary Key value entries (Lookup)

for k,v in mapping:
    for f in os.listdir("."):
        if re.match('1500',f): #Executes code on specific files
            os.rename(f,f.replace(k,v))