Artículos Guías Manuales Sistemas Linux Windows Redes MySql Binario 0 Binario Cero
Artículos Guías Manuales Sistemas Linux Windows Redes MySql Binario 0 Binario Cero

Renombrar-Espacios, script de PowerShell para eliminar espacios en nombres de archivos y carpetas de forma recursiva

Loading

Es habitual encontrarse con árboles de carpetas heredados de sistemas Windows, correos exportados o migraciones de datos donde los nombres de archivos y carpetas contienen espacios. Esto puede causar problemas al:

  • Trabajar con rutas desde la línea de comandos o scripts (los espacios obligan a usar comillas y son una fuente frecuente de errores).
  • Sincronizar o copiar archivos hacia servidores Linux, buckets de almacenamiento en la nube o repositorios Git.
  • Generar URLs o enlaces directos a archivos, donde los espacios deben codificarse (%20).
  • Automatizar procesos con herramientas de línea de comandos (rsync, curl, git, etc.) que tratan el espacio como separador de argumentos.

Renombrar-Espacios.ps1 es un script de PowerShell que recorre una carpeta de forma recursiva y sustituye todos los espacios de los nombres de archivos y subcarpetas por guiones bajos (_), dejando la estructura y el contenido intactos.

¿Qué problema resuelve?

Más allá del simple reemplazo de caracteres, el script está pensado para funcionar de forma segura en entornos reales de Windows, donde aparecen tres problemas típicos:

  1. Orden de renombrado. Si se renombra una carpeta antes que su contenido, las rutas de los archivos que aún faltan por procesar quedan invalidadas. El script procesa primero los elementos más profundos del árbol y termina por los más superficiales, evitando este problema.
  2. Rutas demasiado largas. Windows limita las rutas a 260 caracteres por defecto. Es habitual superar este límite con archivos como correos .eml exportados, que incluyen asuntos largos y metadatos en el propio nombre. El script añade automáticamente el prefijo especial \\?\ (o \\?\UNC\ en rutas de red) para saltarse esa limitación.
  3. Errores puntuales que detienen todo el proceso. Si un solo archivo falla (por permisos, bloqueo del archivo, etc.), un script básico se detendría por completo. Este script captura el error, lo muestra en pantalla y continúa con el resto de archivos y carpetas.

Requisitos

  • Windows con PowerShell 5.1 o superior (viene preinstalado en Windows 10 y 11).
  • Permisos de lectura y escritura sobre la carpeta a procesar.
  • Si la carpeta está en una unidad de red mapeada (por ejemplo Z:), la unidad debe estar conectada antes de ejecutar el script.

Instalación

No requiere instalación. Basta con descargar el archivo Renombrar-Espacios.ps1 y guardarlo en cualquier carpeta local.

Si es la primera vez que ejecutas scripts de PowerShell en el equipo, es posible que necesites habilitar su ejecución. Abre PowerShell y ejecuta una sola vez:

powershell

Set-ExecutionPolicy -Scope CurrentUser RemoteSigned

Esto permite ejecutar scripts locales (como este) mientras sigue exigiendo firma digital para scripts descargados de internet.

Alternativa si no puedes ejecutar como administrador o la política de ejecución no lo permite

Si no tienes permisos para ejecutar Set-ExecutionPolicy (por ejemplo, en un equipo de empresa gestionado por políticas de grupo) o simplemente prefieres no cambiar la configuración del sistema, puedes saltarte la restricción únicamente para esta ejecución, sin necesidad de permisos de administrador:

powershell

powershell -ExecutionPolicy Bypass -File "C:\ruta\a\Renombrar-Espacios.ps1" -Ruta "C:\ruta\a\tu\carpeta"

Y en modo prueba:

powershell

powershell -ExecutionPolicy Bypass -File "C:\ruta\a\Renombrar-Espacios.ps1" -Ruta "C:\ruta\a\tu\carpeta" -DryRun

Esta opción aplica el "bypass" solo a ese proceso de PowerShell concreto: no modifica ninguna configuración persistente del sistema ni afecta a otros scripts.

Uso básico

El script acepta dos parámetros:

ParámetroObligatorioDescripción
-RutaCarpeta raíz desde la que empezar a renombrar de forma recursiva.
-DryRunNoSi se indica, solo muestra qué cambiaría, sin renombrar nada realmente.

Ejecutar en modo real

powershell

.\Renombrar-Espacios.ps1 -Ruta "C:\Users\Juanjo\Documentos"

Ejecutar en modo prueba (recomendado antes de aplicar cambios)

powershell

.\Renombrar-Espacios.ps1 -Ruta "C:\Users\Juanjo\Documentos" -DryRun

En modo -DryRun, el script imprime en pantalla cada renombrado que haría, pero no modifica ningún archivo ni carpeta. Es la forma más segura de comprobar el resultado antes de tocar datos reales.

Ejecutar sobre una unidad de red

powershell

.\Renombrar-Espacios.ps1 -Ruta "Z:\nominas y documentacion administrativa"

Cómo interpretar la salida

Durante la ejecución, el script muestra una línea por cada archivo o carpeta renombrado:

Archivo: 'E:\recycle\Informe de Vida Laboral Sepbre.2024.pdf' -> 'E:\recycle\Informe_de_Vida_Laboral_Sepbre.2024.pdf'
Carpeta: 'Z:\nominas y documentacion administrativa' -> 'Z:\nominas_y_documentacion_administrativa'

Si un nombre destino ya existe, el script no sobrescribe nada; lo omite y avisa:

[AVISO] Ya existe, se omite: Z:\nominas_y_documentacion_administrativa\archivo.pdf

Si ocurre un error al renombrar un elemento concreto (por ejemplo, por bloqueo del archivo o permisos), el script lo marca en rojo y continúa con el resto:

  [ERROR] No se pudo renombrar: 

Al finalizar, se muestra un resumen:

Listo. Elementos renombrados: 42
Elementos con error (omitidos): 1

Detalles técnicos de funcionamiento

  1. Recolección del árbol completo. El script usa Get-ChildItem -Recurse -Force para obtener todos los archivos y carpetas, incluidos los ocultos, dentro de la ruta indicada.
  2. Ordenación por profundidad. Los elementos se ordenan según el número de niveles de su ruta, de mayor a menor profundidad, para procesar siempre primero el contenido más anidado.
  3. Distinción entre archivos y carpetas. Las carpetas no tienen la propiedad DirectoryName (solo los archivos la tienen); el script usa Parent.FullName cuando el elemento es una carpeta.
  4. Compatibilidad con rutas largas. Antes de cada operación de renombrado, el script añade el prefijo \\?\ (rutas locales) o \\?\UNC\ (rutas de red) a la ruta de origen, indicando a Windows que omita el límite estándar de 260 caracteres.
  5. Tolerancia a fallos. Cada renombrado individual se ejecuta dentro de un bloque try/catch; un fallo puntual no interrumpe el procesamiento del resto del árbol.

Recomendaciones de uso

  • Ejecuta siempre primero con -DryRun sobre carpetas con datos importantes, para revisar el resultado antes de aplicar los cambios.
  • Haz una copia de seguridad si vas a procesar carpetas críticas (nóminas, documentación administrativa, correos exportados, etc.), especialmente en la primera ejecución.
  • Cierra los archivos que puedan estar abiertos en otros programas (Outlook, Word, Excel, PDF) antes de ejecutar el script, ya que un archivo bloqueado no podrá renombrarse.
  • Revisa los avisos y errores al final de la ejecución; los elementos omitidos por "ya existe" no producen pérdida de datos, pero conviene revisarlos manualmente si es relevante.

Limitaciones conocidas

  • El script solo reemplaza el carácter espacio. No normaliza otros caracteres problemáticos como tildes, ñ, guiones, paréntesis o el carácter (guión largo), que en algunos casos también dan problemas en rutas o URLs.
  • No incluye una función de deshacer. Se recomienda probar con -DryRun y/o mantener una copia de seguridad antes de ejecutar en modo real sobre datos importantes.
  • En rutas de red muy largas, aunque el prefijo \\?\UNC\ soluciona la mayoría de casos, algunos servidores NAS o SMB antiguos pueden seguir teniendo limitaciones propias no relacionadas con PowerShell.

Código fuente

El script completo (Renombrar-Espacios.ps1) se entrega como archivo independiente junto a este manual.

<#
.SYNOPSIS
    Renombra recursivamente archivos y carpetas reemplazando espacios por guiones bajos.

.DESCRIPTION
    Recorre una ruta de forma recursiva y renombra todos los archivos y carpetas
    cuyo nombre contenga espacios, sustituyendo cada espacio por "_".
    Procesa primero los elementos mas profundos para no romper rutas.

.PARAMETER Ruta
    Carpeta raiz desde la que empezar a renombrar.

.PARAMETER DryRun
    Si se indica, solo muestra los cambios que se harian, sin aplicarlos.

.EXAMPLE
    .\Renombrar-Espacios.ps1 -Ruta "C:\Users\Juanjo\Documentos"

.EXAMPLE
    .\Renombrar-Espacios.ps1 -Ruta "C:\Users\Juanjo\Documentos" -DryRun
#>

param(
    [Parameter(Mandatory = $true)]
    [string]$Ruta,

    [switch]$DryRun
)

if (-not (Test-Path -LiteralPath $Ruta -PathType Container)) {
    Write-Host "Error: la ruta '$Ruta' no existe o no es una carpeta." -ForegroundColor Red
    exit 1
}

Write-Host "Procesando: $Ruta"
if ($DryRun) {
    Write-Host "*** MODO PRUEBA (DryRun): no se modificara nada ***`n" -ForegroundColor Yellow
}

# Prefijo que le indica a Windows que soporte rutas largas (> 260 caracteres)
function Convertir-RutaLarga {
    param([string]$Path)
    if ($Path -match '^\\\\') {
        # Ruta de red \\servidor\recurso -> \\?\UNC\servidor\recurso
        return $Path -replace '^\\\\', '\\?\UNC\'
    }
    else {
        return "\\?\$Path"
    }
}

# Obtenemos TODOS los elementos (archivos y carpetas) de forma recursiva,
# y los ordenamos por profundidad de ruta descendente (mas profundos primero)
# para que renombrar una carpeta no invalide las rutas de su contenido.
$items = Get-ChildItem -LiteralPath $Ruta -Recurse -Force |
    Sort-Object { ($_.FullName -split '\\').Count } -Descending

$contador = 0
$errores = 0

foreach ($item in $items) {
    if ($item.Name -match ' ') {
        $nuevoNombre = $item.Name -replace ' ', '_'

        # DirectoryName solo existe en archivos; en carpetas usamos Parent.FullName
        if ($item.PSIsContainer) {
            $carpetaPadre = $item.Parent.FullName
        }
        else {
            $carpetaPadre = $item.DirectoryName
        }

        $destino = Join-Path -Path $carpetaPadre -ChildPath $nuevoNombre

        if (Test-Path -LiteralPath (Convertir-RutaLarga $destino)) {
            Write-Host "[AVISO] Ya existe, se omite: $destino" -ForegroundColor Yellow
            continue
        }

        $tipo = if ($item.PSIsContainer) { "Carpeta" } else { "Archivo" }
        Write-Host "$tipo`: '$($item.FullName)' -> '$destino'"

        if (-not $DryRun) {
            try {
                $origenLargo = Convertir-RutaLarga $item.FullName
                Rename-Item -LiteralPath $origenLargo -NewName $nuevoNombre -ErrorAction Stop
                $contador++
            }
            catch {
                Write-Host "  [ERROR] No se pudo renombrar: $($_.Exception.Message)" -ForegroundColor Red
                $errores++
            }
        }
        else {
            $contador++
        }
    }
}

Write-Host "`nListo. Elementos renombrados: $contador"
if ($errores -gt 0) {
    Write-Host "Elementos con error (omitidos): $errores" -ForegroundColor Red
}

You may also like...

WP Twitter Auto Publish Powered By : XYZScripts.com