Массовое переименование файлов на основе поиска - PullRequest
6 голосов
/ 10 ноября 2010

У меня есть папка, полная файлов изображений, таких как

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

Ответы [ 9 ]

7 голосов
/ 10 ноября 2010

Вот простой скрипт 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.

5 голосов
/ 10 ноября 2010

Это будет работать для вашей проблемы:

#!/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 голосов
/ 04 июня 2014

Я изменил код Уэсли, чтобы он работал в моей конкретной ситуации.У меня был файл сопоставления "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, так что это был хороший опыт обучения для меня.

2 голосов
/ 10 ноября 2010

Это очень просто сделать в 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
2 голосов
/ 10 ноября 2010

Переписано использование генераторов Уэсли:

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)
1 голос
/ 10 ноября 2010
#!/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
1 голос
/ 10 ноября 2010

Прочитайте в текстовом файле, создайте хэш с текущим именем файла, так что files['1500000704'] = 'SH103239' и так далее. Затем просмотрите файлы в текущем каталоге, возьмите новое имя файла из хэша и переименуйте его.

0 голосов
/ 03 октября 2017
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))
0 голосов
/ 10 ноября 2010

Вот забавный маленький хак:

paste -d " " lookupfile.txt lookupfile.txt | cut -d " " -f 2,3 | sed "s/\([ ]\|$\)/_full.jpg /g;s/^/mv /" | sh
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...