пакетное переименование файлов 100K с помощью python

у меня есть папка с более чем 100 000 файлов, все пронумерованы с тем же заглушкой, но без ведущих нулей, и номера не всегда смежны (обычно они есть, но есть пробелы) e.g:

file-21.png, 
file-22.png,  
file-640.png, 
file-641.png, 
file-642.png, 
file-645.png, 
file-2130.png, 
file-2131.png, 
file-3012.png, 

etc.

Я хотел бы пакетно обработать это, чтобы создать дополненные, непрерывные файлы. е.г:

file-000000.png, 
file-000001.png, 
file-000002.png, 
file-000003.png, 

когда я разбираю папку с for filename in os.listdir('.'): файлы не появляются в том порядке, в котором я хотел бы их. Понятно, что они приходят

 file-1, 
 file-1x, 
 file-1xx, 
 file-1xxx,

etc. тогда

 file-2, 
 file-2x, 
 file-2xx, 

etc. Как я могу заставить его пройти в порядке числового значения? Я полный python noob, но, глядя на документы, я предполагаю, что могу использовать map для создания нового списка, отфильтровывая только числовую часть, а затем сортировать этот список, а затем повторять это? С более чем 100K файлами это может быть тяжело. Любые советы приветствуются!

6 ответов


import re
thenum = re.compile('^file-(\d+)\.png$')

def bynumber(fn):
  mo = thenum.match(fn)
  if mo: return int(mo.group(1))

allnames = os.listdir('.')
allnames.sort(key=bynumber)

Теперь у вас есть файлы в нужном порядке и петли

for i, fn in enumerate(allnames):
  ...

используя прогрессивное число i (что будет 0, 1, 2,...) проложенный, как вы хотите, в месте назначения-имя.


есть три шага. Первый-получить все имена файлов. Второй-преобразование имен файлов. Третий-переименование.

если все файлы находятся в одной папке, то glob должен работать.

import glob
filenames = glob.glob("/path/to/folder/*.txt")

Далее, вы хотите изменить имя файла. Для этого можно печатать с помощью прокладки.

>>> filename = "file-338.txt"
>>> import os
>>> fnpart = os.path.splitext(filename)[0]
>>> fnpart
'file-338'
>>> _, num = fnpart.split("-")
>>> num.rjust(5, "0")
'00338'
>>> newname = "file-%s.txt" % num.rjust(5, "0")
>>> newname
'file-00338.txt'

теперь вам нужно переименовать их всех. os.rename делает именно это.

os.rename(filename, newname)

это:

for filename in glob.glob("/path/to/folder/*.txt"): # loop through each file
    newname = make_new_filename(filename) # create a function that does step 2, above
    os.rename(filename, newname)

спасибо всем за ваши предложения, я постараюсь их все, чтобы узнать различные подходы. Решение, которое я выбрал, основано на использовании естественной сортировки в моем списке файлов, а затем повторении этого для переименования. Это был один из предложенных ответов, но по какой-то причине он исчез, поэтому я не могу отметить его как принятый!

import os
files = os.listdir('.')
natsort(files)
index = 0
for filename in files:
    os.rename(filename, str(index).zfill(7)+'.png')
    index += 1

где natsort определяется в http://code.activestate.com/recipes/285264-natural-string-sorting/


Почему бы вам не сделать это в два этапа. Проанализируйте все файлы и переименуйте их с помощью добавленных номеров, а затем запустите другой скрипт, который возьмет эти файлы, которые теперь отсортированы правильно, и переименует их, чтобы они были смежными?


1) Возьмите номер в имени файла. 2) левый блокнот с нулями 3) сохранить имя.


def renamer():
    for iname in os.listdir('.'):
        first, second = iname.replace(" ", "").split("-")
        number, ext = second.split('.')
        first, number, ext = first.strip(), number.strip(), ext.strip()
        number = '0'*(6-len(number)) + number  # pad the number to be 7 digits long
        oname = first + "-" + number + '.' + ext
        os.rename(iname, oname)
    print "Done"

надеюсь, что это помогает