Renomeação em lote de arquivos em um diretório

102

Existe uma maneira fácil de renomear um grupo de arquivos já contidos em um diretório, usando Python?

Exemplo: tenho um diretório cheio de arquivos * .doc e desejo renomeá-los de forma consistente.

X.doc -> "novo (X) .doc"

Y.doc -> "novo (Y) .doc"

Nate
fonte

Respostas:

114

Essa renomeação é bastante fácil, por exemplo, com módulos os e glob :

import glob, os

def rename(dir, pattern, titlePattern):
    for pathAndFilename in glob.iglob(os.path.join(dir, pattern)):
        title, ext = os.path.splitext(os.path.basename(pathAndFilename))
        os.rename(pathAndFilename, 
                  os.path.join(dir, titlePattern % title + ext))

Você pode então usá-lo em seu exemplo desta forma:

rename(r'c:\temp\xx', r'*.doc', r'new(%s)')

O exemplo acima irá converter todos os *.docarquivos em c:\temp\xxdir para new(%s).doc, onde %sé o nome de base anterior do arquivo (sem extensão).

DzinX
fonte
1
Como o %símbolo é usado no comando os.path.join(dir, titlePattern % title + ext)? Eu sei que %é para operação de módulo e também é usado como um operador de formatação. Mas geralmente é seguido por sou fpara especificar o formato. Por que nada (espaço) está imediatamente após %no referido comando?
Shashank Sawant,
3
@ShashankSawant É realmente um operador de formatação. Consulte Operações de formatação de string para obter a documentação e exemplos de uso.
DzinX de
133

Eu prefiro escrever pequenas linhas para cada substituição que tenho que fazer, em vez de fazer um código mais genérico e complexo. Por exemplo:

Isso substitui todos os sublinhados por hifens em qualquer arquivo não oculto no diretório atual

import os
[os.rename(f, f.replace('_', '-')) for f in os.listdir('.') if not f.startswith('.')]
Cesar Canassa
fonte
4
Muito mais fácil do que os outros métodos. É por isso que adoro Python.
Dan Gayle
Perdi muito tempo hoje tentando descobrir por que meu comando "renomear" não estava funcionando - deveria ter vindo aqui primeiro! Excelente one-liner Pythonic!
Devin
Não funciona porque o Windows continua reorganizando os arquivos em ordem alfabética após cada um rename:(
ytpillai
4
Excelente, mas só funciona com um dir sem sub dir.
Hill
se você conseguir no such file errorapenas lembrar, os.renameprecisa do caminho completo
Windsooon
22

Se você não se importa em usar expressões regulares, esta função lhe dará muito poder para renomear arquivos:

import re, glob, os

def renamer(files, pattern, replacement):
    for pathname in glob.glob(files):
        basename= os.path.basename(pathname)
        new_filename= re.sub(pattern, replacement, basename)
        if new_filename != basename:
            os.rename(
              pathname,
              os.path.join(os.path.dirname(pathname), new_filename))

Portanto, em seu exemplo, você poderia fazer (assumindo que seja o diretório atual onde os arquivos estão):

renamer("*.doc", r"^(.*)\.doc$", r"new(\1).doc")

mas você também pode reverter para os nomes de arquivo iniciais:

renamer("*.doc", r"^new\((.*)\)\.doc", r"\1.doc")

e mais.

tzot
fonte
11

Eu tenho isso para simplesmente renomear todos os arquivos em subpastas da pasta

import os

def replace(fpath, old_str, new_str):
    for path, subdirs, files in os.walk(fpath):
        for name in files:
            if(old_str.lower() in name.lower()):
                os.rename(os.path.join(path,name), os.path.join(path,
                                            name.lower().replace(old_str,new_str)))

Estou substituindo todas as ocorrências de old_str com qualquer case por new_str.

Kiriloff
fonte
Este código é realmente usado para substituir qualquer parte do título de um arquivo em um diretório.
geoJshaun de
6

Experimente: http://www.mattweber.org/2007/03/04/python-script-renamepy/

Gosto de que meus arquivos de música, filme e imagem sejam nomeados de uma determinada maneira. Quando eu faço download de arquivos da Internet, eles geralmente não seguem minha convenção de nomenclatura. Descobri-me renomeando manualmente cada arquivo para se adequar ao meu estilo. Isso envelheceu muito rápido, então decidi escrever um programa para fazer isso por mim.

Este programa pode converter o nome do arquivo para todas as letras minúsculas, substituir as strings no nome do arquivo pelo que você quiser e cortar qualquer número de caracteres da frente ou de trás do nome do arquivo.

O código-fonte do programa também está disponível.

xsl
fonte
1
Infelizmente o link está quebrado, alguém sabe onde está o código fonte?
ryanpcmcquen
6

Escrevi um script python sozinho. Toma como argumentos o caminho do diretório no qual os arquivos estão presentes e o padrão de nomenclatura que deseja usar. No entanto, ele renomeia anexando um número incremental (1, 2, 3 e assim por diante) ao padrão de nomenclatura fornecido.

import os
import sys

# checking whether path and filename are given.
if len(sys.argv) != 3:
    print "Usage : python rename.py <path> <new_name.extension>"
    sys.exit()

# splitting name and extension.
name = sys.argv[2].split('.')
if len(name) < 2:
    name.append('')
else:
    name[1] = ".%s" %name[1]

# to name starting from 1 to number_of_files.
count = 1

# creating a new folder in which the renamed files will be stored.
s = "%s/pic_folder" % sys.argv[1]
try:
    os.mkdir(s)
except OSError:
    # if pic_folder is already present, use it.
    pass

try:
    for x in os.walk(sys.argv[1]):
        for y in x[2]:
            # creating the rename pattern.
            s = "%spic_folder/%s%s%s" %(x[0], name[0], count, name[1])
            # getting the original path of the file to be renamed.
            z = os.path.join(x[0],y)
            # renaming.
            os.rename(z, s)
            # incrementing the count.
            count = count + 1
except OSError:
    pass

Espero que funcione para voce.

Harisibrahimkv
fonte
5

Esteja no diretório onde você precisa fazer a renomeação.

import os
# get the file name list to nameList
nameList = os.listdir() 
#loop through the name and rename
for fileName in nameList:
    rename=fileName[15:28]
    os.rename(fileName,rename)
#example:
#input fileName bulk like :20180707131932_IMG_4304.JPG
#output renamed bulk like :IMG_4304.JPG
Ajay Chandran
fonte
para "estar no diretório ..." useos.chdir(path_of_directory)
MagTun
2
directoryName = "Photographs"
filePath = os.path.abspath(directoryName)
filePathWithSlash = filePath + "\\"

for counter, filename in enumerate(os.listdir(directoryName)):

    filenameWithPath = os.path.join(filePathWithSlash, filename)

    os.rename(filenameWithPath, filenameWithPath.replace(filename,"DSC_" + \
          str(counter).zfill(4) + ".jpg" ))

# e.g. filename = "photo1.jpg", directory = "c:\users\Photographs"        
# The string.replace call swaps in the new filename into 
# the current filename within the filenameWitPath string. Which    
# is then used by os.rename to rename the file in place, using the  
# current (unmodified) filenameWithPath.

# os.listdir delivers the filename(s) from the directory
# however in attempting to "rename" the file using os 
# a specific location of the file to be renamed is required.

# this code is from Windows 
frank__aguirre
fonte
2

Tive um problema semelhante, mas queria acrescentar texto ao início do nome do arquivo de todos os arquivos em um diretório e usei um método semelhante. Veja o exemplo abaixo:

folder = r"R:\mystuff\GIS_Projects\Website\2017\PDF"

import os


for root, dirs, filenames in os.walk(folder):


for filename in filenames:  
    fullpath = os.path.join(root, filename)  
    filename_split = os.path.splitext(filename) # filename will be filename_split[0] and extension will be filename_split[1])
    print fullpath
    print filename_split[0]
    print filename_split[1]
    os.rename(os.path.join(root, filename), os.path.join(root, "NewText_2017_" + filename_split[0] + filename_split[1]))
Amber Davis
fonte
1

quanto a mim no meu diretório, tenho vários subdiretórios, cada subdiretório tem muitas imagens. Quero alterar todas as imagens dos subdiretórios para 1.jpg ~ n.jpg

def batch_rename():
    base_dir = 'F:/ad_samples/test_samples/'
    sub_dir_list = glob.glob(base_dir + '*')
    # print sub_dir_list # like that ['F:/dir1', 'F:/dir2']
    for dir_item in sub_dir_list:
        files = glob.glob(dir_item + '/*.jpg')
        i = 0
        for f in files:
            os.rename(f, os.path.join(dir_item, str(i) + '.jpg'))
            i += 1

(minha própria resposta) https://stackoverflow.com/a/45734381/6329006

Jayhello
fonte
1
#  another regex version
#  usage example:
#  replacing an underscore in the filename with today's date
#  rename_files('..\\output', '(.*)(_)(.*\.CSV)', '\g<1>_20180402_\g<3>')
def rename_files(path, pattern, replacement):
    for filename in os.listdir(path):
        if re.search(pattern, filename):
            new_filename = re.sub(pattern, replacement, filename)
            new_fullname = os.path.join(path, new_filename)
            old_fullname = os.path.join(path, filename)
            os.rename(old_fullname, new_fullname)
            print('Renamed: ' + old_fullname + ' to ' + new_fullname
Dan
fonte
1

Se desejar modificar os nomes dos arquivos em um editor (como o vim), a biblioteca de cliques vem com o comando click.edit(), que pode ser usado para receber entrada do usuário de um editor. Aqui está um exemplo de como ele pode ser usado para refatorar arquivos em um diretório.

import click
from pathlib import Path

# current directory
direc_to_refactor = Path(".")

# list of old file paths
old_paths = list(direc_to_refactor.iterdir())

# list of old file names
old_names = [str(p.name) for p in old_paths]

# modify old file names in an editor,
# and store them in a list of new file names
new_names = click.edit("\n".join(old_names)).split("\n")

# refactor the old file names
for i in range(len(old_paths)):
    old_paths[i].replace(direc_to_refactor / new_names[i])

Eu escrevi um aplicativo de linha de comando que usa a mesma técnica, mas que reduz a volatilidade desse script e vem com mais opções, como refatoração recursiva. Aqui está o link para a página do github . Isso é útil se você gosta de aplicativos de linha de comando e está interessado em fazer algumas edições rápidas nos nomes dos arquivos. (Meu aplicativo é semelhante ao comando "bulkrename" encontrado no ranger ).

Jim Shaddix
fonte
1
Embora encorajemos links para recursos externos, desencorajamos respostas apenas de link, pois elas se tornam inúteis quando o link expira. Atualize sua resposta para incluir a resposta à pergunta :)
IT Delinquent
Absolutamente. Vou editar minha postagem. Esta é minha primeira contribuição, então agradeço a orientação!
Jim Shaddix
0

Este código funcionará

A função leva exatamente dois argumentos f_patth como seu caminho para renomear arquivo e new_name como seu novo nome para o arquivo.

import glob2
import os


def rename(f_path, new_name):
    filelist = glob2.glob(f_path + "*.ma")
    count = 0
    for file in filelist:
        print("File Count : ", count)
        filename = os.path.split(file)
        print(filename)
        new_filename = f_path + new_name + str(count + 1) + ".ma"
        os.rename(f_path+filename[1], new_filename)
        print(new_filename)
        count = count + 1
Murthy Annavajhula
fonte