Cambio de nombre por lotes de archivos en un directorio

102

¿Existe una manera fácil de cambiar el nombre de un grupo de archivos que ya se encuentran en un directorio, usando Python?

Ejemplo: tengo un directorio lleno de archivos * .doc y quiero cambiarles el nombre de manera coherente.

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

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

Nate
fuente

Respuestas:

114

Este cambio de nombre es bastante fácil, por ejemplo, con los módulos os y 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))

Luego puede usarlo en su ejemplo de esta manera:

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

El ejemplo anterior convertirá todos los *.docarchivos en c:\temp\xxdir a new(%s).doc, donde %ses el nombre base anterior del archivo (sin extensión).

DzinX
fuente
1
¿Cómo se %usa el símbolo en el comando os.path.join(dir, titlePattern % title + ext)? Sé que %es para operación de módulo y también se usa como operador de formato. Pero generalmente va seguido de so fpara especificar el formato. ¿Por qué no hay nada (espacio) inmediatamente después %en dicho comando?
Shashank Sawant
3
@ShashankSawant De hecho, es un operador de formato. Consulte Operaciones de formato de cadena para obtener documentación y ejemplos de uso.
DzinX
133

Prefiero escribir pequeñas líneas para cada reemplazo que tengo que hacer en lugar de hacer un código más genérico y complejo. P.ej:

Esto reemplaza todos los guiones bajos con guiones en cualquier archivo no oculto en el directorio actual

import os
[os.rename(f, f.replace('_', '-')) for f in os.listdir('.') if not f.startswith('.')]
Cesar Canassa
fuente
4
Mucho más fácil que los otros métodos. ESTA es la razón por la que amo Python.
Dan Gayle
Perdí demasiado tiempo hoy tratando de averiguar por qué mi comando "renombrar" no estaba funcionando - ¡debería haber venido aquí primero! ¡Gran Pythonic one-liner!
Devin
No funciona porque Windows sigue reordenando los archivos por orden alfabético después de cada rename:(
ytpillai
4
Excelente pero solo funciona con un directorio sin subdirectorio.
Hill
si lo obtiene, no such file errorrecuerde que os.renamenecesita la ruta completa
Windsooon
22

Si no le importa usar expresiones regulares, entonces esta función le dará mucho poder para cambiar el nombre de los archivos:

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

Entonces, en su ejemplo, podría hacer (asumiendo que es el directorio actual donde están los archivos):

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

pero también puede volver a los nombres de archivo iniciales:

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

y más.

tzot
fuente
11

Tengo esto para simplemente cambiar el nombre de todos los archivos en las subcarpetas de la carpeta

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

Estoy reemplazando todas las apariciones de old_str con cualquier caso por new_str.

Kiriloff
fuente
Este código se utiliza realmente para reemplazar cualquier parte del título de un archivo en un directorio.
geoJshaun
6

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

Me gusta que mis archivos de música, películas e imágenes tengan un nombre determinado. Cuando descargo archivos de Internet, generalmente no siguen mi convención de nomenclatura. Me encontré cambiando manualmente el nombre de cada archivo para adaptarlo a mi estilo. Esto envejeció muy rápido, así que decidí escribir un programa para hacerlo por mí.

Este programa puede convertir el nombre de archivo a todo en minúsculas, reemplazar cadenas en el nombre de archivo con lo que desee y recortar cualquier número de caracteres del anverso o reverso del nombre del archivo.

El código fuente del programa también está disponible.

xsl
fuente
1
Desafortunadamente, el enlace está roto, ¿alguien sabe dónde está el código fuente?
ryanpcmcquen
6

He escrito un script de Python por mi cuenta. Toma como argumentos la ruta del directorio en el que están presentes los archivos y el patrón de nomenclatura que desea utilizar. Sin embargo, cambia el nombre adjuntando un número incremental (1, 2, 3, etc.) al patrón de nomenclatura que le da.

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 esto funcione para usted.

harisibrahimkv
fuente
5

Esté en el directorio donde necesita realizar el cambio de nombre.

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
fuente
para "estar en el directorio ..." 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
fuente
2

Tuve un problema similar, pero quería agregar texto al principio del nombre de archivo de todos los archivos en un directorio y usé un método similar. Vea el ejemplo a continuación:

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]))
Ámbar davis
fuente
1

En cuanto a mí, en mi directorio tengo varios subdirectorios, cada subdirectorio tiene muchas imágenes.Quiero cambiar todas las imágenes de subdirectorios a 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

(mi propia respuesta) https://stackoverflow.com/a/45734381/6329006

Jayhello
fuente
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
fuente
1

Si desea modificar los nombres de los archivos en un editor (como vim), la biblioteca de clics viene con el comando click.edit(), que se puede usar para recibir información del usuario de un editor. A continuación, se muestra un ejemplo de cómo se puede utilizar para refactorizar archivos en un directorio.

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])

Escribí una aplicación de línea de comandos que usa la misma técnica, pero que reduce la volatilidad de este script y viene con más opciones, como la refactorización recursiva. Aquí está el enlace a la página de github . Esto es útil si le gustan las aplicaciones de línea de comandos y está interesado en realizar algunas ediciones rápidas en los nombres de los archivos. (Mi aplicación es similar al comando "bulkrename" que se encuentra en Ranger ).

Jim Shaddix
fuente
1
Si bien fomentamos los enlaces a recursos externos, desaconsejamos las respuestas de solo enlace, ya que se vuelven inútiles cuando el enlace caduca. Actualice su respuesta para incluir la respuesta a la pregunta :)
IT Delinquent
Absolutamente. Editaré mi publicación. Esta es mi primera contribución, ¡así que agradezco la orientación!
Jim Shaddix
0

Este código funcionará

La función toma exactamente dos argumentos f_patth como su ruta para cambiar el nombre del archivo y new_name como su nuevo nombre para el archivo.

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
fuente