Python
Obtener fácilmente todos los archivos de un directorio: explicación en Python

Obtener fácilmente todos los archivos de un directorio: explicación en Python

MoeNagy Dev

Obtener todos los archivos de un directorio con Python

Importancia de listar archivos en un directorio

Comprender la estructura de archivos de tu proyecto es crucial para la gestión de archivos y la automatización efectivas. Poder listar los archivos en un directorio puede ayudarte a:

  • Comprender la organización de archivos de tu proyecto: Al listar los archivos en un directorio, puedes ver rápidamente qué archivos están presentes, sus nombres y su organización dentro de la estructura del directorio.
  • Automatizar tareas relacionadas con archivos: Listar archivos de forma programática te permite realizar diversas tareas, como copias de seguridad de archivos, organización de archivos multimedia o análisis de código fuente, de manera automatizada y eficiente.
  • Analizar contenido y metadatos de archivos: Una vez que tienes una lista de archivos, puedes procesar la información adicionalmente, como el tamaño del archivo, el tiempo de modificación u otros metadatos, para obtener información sobre tu proyecto.

Manejo básico de archivos en Python

Antes de explorar cómo listar archivos en un directorio, repasemos rápidamente los conceptos básicos del manejo de archivos en Python.

Abrir y cerrar archivos

En Python, puedes abrir un archivo usando la función open(). La sintaxis básica es:

archivo = open("nombre_archivo.txt", "r")
# Realizar operaciones en el archivo
archivo.close()

El segundo argumento de la función open() especifica el modo, como "r" para lectura, "w" para escritura o "a" para agregar.

Es importante cerrar el archivo después de haber terminado con él para asegurarse de que se guarden los cambios y se liberen correctamente los recursos del sistema.

Leer y escribir contenido de un archivo

Una vez que un archivo está abierto, puedes leer su contenido usando el método read():

archivo = open("nombre_archivo.txt", "r")
contenido = archivo.read()
print(contenido)
archivo.close()

Para escribir en un archivo, puedes usar el método write():

archivo = open("nombre_archivo.txt", "w")
archivo.write("Este es algún contenido que se escribirá en el archivo.")
archivo.close()

Listar archivos en un directorio

Ahora, veamos cómo listar los archivos en un directorio usando Python.

Usando el módulo os

El módulo os en Python proporciona un conjunto de funciones para interactuar con el sistema operativo, incluyendo la gestión de archivos y directorios. Para listar los archivos en un directorio, utilizaremos la función os.listdir().

import os
 
directorio = "/ruta/al/directorio"
archivos = os.listdir(directorio)
print(archivos)

Esto imprimirá una lista de todos los archivos y directorios dentro del directorio especificado.

Ten en cuenta que os.listdir() devuelve los nombres de los archivos y directorios, pero no sus rutas completas. Si necesitas las rutas completas, puedes combinar os.listdir() con os.path.join():

import os
 
directorio = "/ruta/al/directorio"
rutas_archivos = [os.path.join(directorio, nombre_archivo) for nombre_archivo in os.listdir(directorio)]
print(rutas_archivos)

Esto te dará una lista de rutas de archivos completas, incluyendo el directorio y el nombre del archivo.

Manejo de rutas relativas y absolutas

Cuando trabajas con rutas de archivos, puedes usar rutas relativas o absolutas. Las rutas relativas se basan en el directorio de trabajo actual, mientras que las rutas absolutas especifican la ruta completa desde el directorio raíz.

Para obtener el directorio de trabajo actual, puedes usar os.getcwd():

import os
 
directorio_actual = os.getcwd()
print(directorio_actual)

Luego puedes usar esta información para construir rutas relativas o absolutas según sea necesario.

Filtrar archivos por extensión

A menudo, es posible que desees listar solo los archivos con una extensión específica, como .txt o .py. Puedes lograr esto utilizando varias técnicas.

Comprobar las extensiones de los archivos

Una forma de filtrar archivos por extensión es comprobar la extensión del archivo mediante operaciones de cadena:

import os
 
directorio = "/ruta/al/directorio"
archivos_txt = [f for f in os.listdir(directorio) if f.endswith(".txt")]
print(archivos_txt)

Esto utiliza una comprensión de lista para crear una nueva lista que contenga solo los archivos con la extensión .txt.

Alternativamente, puedes usar la función os.path.splitext() para extraer la extensión del archivo:

import os
 
directorio = "/ruta/al/directorio"
archivos_py = [f for f in os.listdir(directorio) if os.path.splitext(f)[1] == ".py"]
print(archivos_py)

Este enfoque separa el nombre de archivo y la extensión, lo que te permite comprobar directamente la extensión.

Travesía recursiva de subdirectorios

Si tu proyecto tiene una estructura de directorios compleja con subdirectorios, es posible que desees listar recursivamente todos los archivos en todo el árbol de directorios. La función os.walk() puede ayudarte con esta tarea.

import os
 
directorio = "/ruta/al/directorio"
for raiz, dirs, archivos in os.walk(directorio):
    for archivo in archivos:
        print(os.path.join(raiz, archivo))

La función os.walk() proporciona tres valores para cada directorio que atraviesa:

  1. raiz: El directorio actual que se está procesando.
  2. dirs: Una lista de subdirectorios en el directorio actual.
  3. archivos: Una lista de archivos en el directorio actual.

Al iterar sobre la lista archivos, puedes acceder a la ruta completa de cada archivo en el árbol de directorios.

Ordenar y organizar listas de archivos

Una vez que tienes una lista de archivos, es posible que desees ordenarlos u organizarlos de una manera específica. La función sorted() incorporada de Python puede ayudarte con esto.

Ordenación alfabética

Para ordenar la lista de archivos alfabéticamente, puedes usar la función sorted():

import os
 
directorio = "/ruta/al/directorio"
archivos = sorted(os.listdir(directorio))
print(archivos)

Esto ordenará la lista de archivos en orden alfabético.

Ordenación por tamaño de archivo o tiempo de modificación

También puede ordenar la lista de archivos según el tamaño del archivo o la hora de modificación. Para hacer esto, puede proporcionar una función key personalizada a la función sorted().

import os
 
directory = "/path/to/directory"
files = sorted(os.listdir(directory), key=lambda x: os.path.getsize(os.path.join(directory, x)), reverse=True)
print(files)

Esto ordenará la lista de archivos en orden descendente según el tamaño del archivo.

Para ordenar por hora de modificación, puede usar os.path.getmtime() en lugar de os.path.getsize():

import os
from datetime import datetime
 
directory = "/path/to/directory"
files = sorted(os.listdir(directory), key=lambda x: os.path.getmtime(os.path.join(directory, x)), reverse=True)
print(files)

Esto ordenará la lista de archivos en orden descendente según la hora de modificación.

Trabajando con metadatos de archivos

Además de los nombres y rutas de archivo, es posible que también desee obtener información sobre los archivos, como su tamaño y hora de modificación. Python proporciona funciones para acceder a estos metadatos.

Obtener tamaño de archivo y hora de modificación

Puede usar la función os.path.getsize() para obtener el tamaño de un archivo y os.path.getmtime() para obtener la última hora de modificación.

import os
from datetime import datetime
 
directory = "/path/to/directory"
filename = "example.txt"
file_path = os.path.join(directory, filename)
 
file_size = os.path.getsize(file_path)
file_mtime = os.path.getmtime(file_path)
print(f"Tamaño del archivo: {file_size} bytes")
print(f"Última modificación: {datetime.fromtimestamp(file_mtime)}")

Esto imprimirá el tamaño del archivo en bytes y la última hora de modificación del archivo.

Formateo de información sobre tamaño de archivo y hora

Para que la información sobre el tamaño de archivo y la hora sea más legible, puede formatearlos adecuadamente.

import os
from datetime import datetime
 
directory = "/path/to/directory"
filename = "example.txt"
file_path = os.path.join(directory, filename)
 
file_size = os.path.getsize(file_path)
file_mtime = os.path.getmtime(file_path)
 
# Formateo del tamaño del archivo
if file_size < 1024:
    file_size_str = f"{file_size} bytes"
elif file_size < 1024 * 1024:
    file_size_str = f"{file_size / 1024:.2f} KB"
else:
    file_size_str = f"{file_size / (1024 * 1024):.2f} MB"
 
# Formateo de la hora de modificación
file_mtime_str = datetime.fromtimestamp(file_mtime).strftime("%Y-%m-%d %H:%M:%S")
 
print(f"Tamaño del archivo: {file_size_str}")
print(f"Última modificación: {file_mtime_str}")

Esto imprimirá el tamaño del archivo en un formato más legible (bytes, KB o MB) y la hora de modificación en una cadena de fecha y hora formateada.

Manejo de errores y casos límite

Al trabajar con operaciones de archivos, es importante manejar los errores potenciales y los casos límite correctamente. La excepción OSError incorporada en Python puede ayudar en esto.

import os
 
directory = "/path/to/directory"
 
try:
    files = os.listdir(directory)
    for file in files:
        file_path = os.path.join(directory, file)
        file_size = os.path.getsize(file_path)
        print(f"Archivo: {file}, Tamaño: {file_size} bytes")
except OSError as e:
    print(f"Error: {e}")
    print("No se puede acceder al directorio o recuperar la información del archivo.")

En este ejemplo, encapsulamos la obtención de la lista de archivos y la recuperación del tamaño del archivo en un bloque try-except para capturar cualquier excepción OSError que pueda ocurrir, como cuando el directorio no es accesible o un archivo no se puede leer.

Al manejar estas excepciones, se puede proporcionar un mensaje de error más adecuado en lugar de permitir que el programa se bloquee.

Aplicaciones prácticas y casos de uso

Ahora que tiene una comprensión sólida de cómo enumerar archivos en un directorio, exploremos algunas aplicaciones prácticas y casos de uso.

Copia de seguridad y sincronización de archivos

Un caso de uso común es crear copias de seguridad de archivos o sincronizar archivos entre ubicaciones diferentes. Al listar los archivos en un directorio, puede identificar qué archivos deben hacer una copia de seguridad o sincronizarse.

import os
import shutil
 
source_dir = "/path/to/source/directory"
backup_dir = "/path/to/backup/directory"
 
for filename in os.listdir(source_dir):
    src_path = os.path.join(source_dir, filename)
    dst_path = os.path.join(backup_dir, filename)
    shutil.copy2(src_path, dst_path)
    print(f"Copiado de seguridad: {filename}")

Este ejemplo copia todos los archivos de source_dir al directorio backup_dir, creando efectivamente una copia de seguridad de los archivos.

Organización de archivos multimedia

Otro caso de uso es organizar archivos multimedia (por ejemplo, fotos, videos) según sus extensiones de archivo o metadatos. Al listar los archivos en un directorio, puede ordenarlos y moverlos a subdirectorios apropiados.

import os
import shutil
 
media_dir = "/path/to/media/directory"
photo_dir = "/path/to/photos/directory"
video_dir = "/path/to/videos/directory"
 
for filename in os.listdir(media_dir):
    src_path = os.path.join(media_dir, filename)
    if filename.endswith(".jpg") or filename.endswith(".png"):
        dst_path = os.path.join(photo_dir, filename)
    elif filename.endswith(".mp4") or filename.endswith(".mov"):
        dst_path = os.path.join(video_dir, filename)
    else:
        continue
    shutil.move(src_path, dst_path)
    print(f"Movido: {filename}")

Este ejemplo ordena los archivos multimedia en el directorio media_dir según sus extensiones de archivo, moviendo los archivos de imagen al directorio photo_dir y los archivos de video al directorio video_dir.

Análisis de código fuente y gestión de proyectos

Enumerar archivos en un directorio también puede ser útil para el análisis de código fuente y la gestión de proyectos. Puede utilizar las listas de archivos para:

  • Identificar los archivos que componen un proyecto de software.
  • Analizar la estructura y organización de archivos.
  • Generar informes sobre el tamaño de los archivos, las horas de modificación y otros metadatos.

Esta información puede ayudarlo a comprender y gestionar mejor sus proyectos de software.

Conceptos intermedios de Python

Clases y programación orientada a objetos (OOP)

En Python, las clases son los bloques fundamentales de la programación orientada a objetos. Te permiten crear tipos de datos personalizados con sus propios atributos y métodos. Aquí tienes un ejemplo de una clase Car simple:

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
 
    def start(self):
        print(f"El {self.year} {self.make} {self.model} ha arrancado.")
 
    def stop(self):
        print(f"El {self.year} {self.make} {self.model} se ha detenido.")

En este ejemplo, la clase Car tiene tres atributos (make, model y year) y dos métodos (start() y stop()). El método __init__() es un método especial que se llama automáticamente cuando se crea una nueva instancia de la clase Car.

Puedes crear instancias de la clase Car de la siguiente manera:

mi_coche = Car("Toyota", "Corolla", 2015)
mi_coche.start()  # Salida: El 2015 Toyota Corolla ha arrancado.
mi_coche.stop()   # Salida: El 2015 Toyota Corolla se ha detenido.

La programación orientada a objetos también admite la herencia, que te permite crear nuevas clases basadas en las existentes. Aquí tienes un ejemplo de una clase ElectricCar que hereda de la clase Car:

class ElectricCar(Car):
    def __init__(self, make, model, year, battery_capacity):
        super().__init__(make, model, year)
        self.battery_capacity = battery_capacity
 
    def charge(self):
        print(f"El {self.year} {self.make} {self.model} se está cargando.")

La clase ElectricCar hereda los atributos make, model y year, así como los métodos start() y stop(), de la clase Car. También agrega un nuevo atributo (battery_capacity) y un nuevo método (charge()).

mi_coche_electrico = ElectricCar("Tesla", "Model S", 2020, 100)
mi_coche_electrico.start()  # Salida: El 2020 Tesla Model S ha arrancado.
mi_coche_electrico.charge() # Salida: El 2020 Tesla Model S se está cargando.

Módulos y Paquetes

En Python, los módulos son archivos individuales que contienen código, mientras que los paquetes son colecciones de módulos relacionados. Los módulos te permiten organizar tu código y hacerlo reutilizable en diferentes proyectos.

Aquí tienes un ejemplo de un módulo simple llamado math_functions.py:

def add(a, b):
    return a + b
 
def subtract(a, b):
    return a - b
 
def multiply(a, b):
    return a * b
 
def divide(a, b):
    return a / b

Luego puedes importar y usar las funciones de este módulo en otro archivo Python:

from math_functions import add, subtract
print(add(2, 3))  # Salida: 5
print(subtract(5, 3))  # Salida: 2

Los paquetes, por otro lado, te permiten agrupar módulos relacionados. Por ejemplo, podrías crear un paquete math con módulos separados para diferentes tipos de operaciones matemáticas, como arithmetic.py, geometry.py y statistics.py.

math/
    __init__.py
    arithmetic.py
    geometry.py
    statistics.py

Luego puedes importar los módulos desde el paquete math de esta manera:

from math.arithmetic import add, subtract
from math.geometry import calculate_area
from math.statistics import mean, median

Excepciones y Manejo de Errores

En Python, las excepciones son una forma de manejar los errores que ocurren durante la ejecución del programa. Puedes usar bloques try-except para capturar y manejar excepciones.

Aquí tienes un ejemplo de cómo manejar un ZeroDivisionError:

def divide(a, b):
    try:
        result = a / b
        print(f"El resultado es: {result}")
    except ZeroDivisionError:
        print("Error: No se puede dividir por cero.")
 
divide(10, 2)  # Salida: El resultado es: 5.0
divide(10, 0)  # Salida: Error: No se puede dividir por cero.

También puedes usar la cláusula finally para ejecutar código independientemente de si se produjo una excepción o no:

def abrir_archivo(nombre_archivo):
    try:
        archivo = open(nombre_archivo, 'r')
        contenido = archivo.read()
        print(contenido)
    except FileNotFoundError:
        print(f"Error: {nombre_archivo} no encontrado.")
    finally:
        archivo.close()
 
abrir_archivo('ejemplo.txt')

Además, puedes definir tus propias excepciones personalizadas creando una nueva clase que herede de la clase Exception:

class InvalidInputError(Exception):
    pass
 
def calcular_area(forma, *args):
    if forma == 'rectangulo':
        longitud, ancho = args
        return longitud * ancho
    elif forma == 'circulo':
        radio, = args
        return 3.14 * radio ** 2
    else:
        raise InvalidInputError("Forma inválida proporcionada.")
 
try:
    print(calcular_area('rectangulo', 5, 10))  # Salida: 50
    print(calcular_area('circulo', 3))  # Salida: 28.26
    print(calcular_area('triangulo', 3, 4))  # Lanza InvalidInputError
except InvalidInputError as e:
    print(e)

E/S de Archivos y Rutas

Python proporciona funciones y módulos integrados para trabajar con archivos y rutas de archivos. Aquí tienes un ejemplo de cómo leer y escribir en un archivo:

# Escribir en un archivo
with open('ejemplo.txt', 'w') as archivo:
    archivo.write("¡Hola, Mundo!\n")
    archivo.write("Este es un archivo de texto de ejemplo.")
 
# Leer desde un archivo
with open('ejemplo.txt', 'r') as archivo:
    contenido = archivo.read()
    print(contenido)  # Salida: ¡Hola, Mundo!\nEste es un archivo de texto de ejemplo.

La sentencia with se utiliza para asegurarse de que el archivo se cierre correctamente después de completar las operaciones, incluso si se produce una excepción.

También puedes usar el módulo os para trabajar con rutas y directorios de archivos:

import os
 
# Obtener el directorio de trabajo actual
directorio_actual = os.getcwd()
print(directorio_actual)
 
# Unir rutas
ruta_archivo = os.path.join(directorio_actual, 'ejemplo', 'archivo.txt')
print(ruta_archivo)
 
# Comprobar si existe un archivo o directorio
if os.path.exists(ruta_archivo):
    print("El archivo existe.")
else:
    print("El archivo no existe.")

Conclusión

En este tutorial, has aprendido varios conceptos de Python de nivel intermedio, incluyendo:

  • Clases y Programación Orientada a Objetos (POO)
  • Módulos y Paquetes
  • Excepciones y Manejo de Errores
  • Entrada y salida de archivos y rutas

Estos conceptos son esenciales para construir aplicaciones de Python más complejas y robustas. Al comprender y aplicar estas técnicas, puedes escribir un código más limpio, mantenible y versátil.

Recuerda, la mejor forma de mejorar tus habilidades en Python es practicar y experimentar con estos conceptos. Intenta implementarlos en tus propios proyectos y desafiarte continuamente a aprender cosas nuevas.

¡Feliz codificación!

MoeNagy Dev