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

- Link: https://binariocero.com/windows/renombrar-espacios-script-de-powershell-para-eliminar-espacios-en-nombres-de-archivos-y-carpetas-de-forma-recursiva
- Published: 2026-07-11T09:11:01+02:00
- Author: Juan José Fernández Durán

![Loading](https://binariocero.com/wp-content/plugins/page-views-count/ajax-loader-
2x.gif)

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

    ```wp-block-code
    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

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

Y en modo prueba:

powershell

    ```wp-block-code
    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ámetro | Obligatorio | Descripción | 
| `-Ruta` | Sí | Carpeta raíz desde la que empezar a renombrar de forma recursiva. | 
| `-DryRun` | No | Si se indica, solo muestra qué cambiaría, sin renombrar nada realmente. |

### Ejecutar en modo real

powershell

    ```wp-block-code
    .\Renombrar-Espacios.ps1 -Ruta "C:\Users\Juanjo\Documentos"
    ```

### Ejecutar en modo prueba (recomendado antes de aplicar cambios)

powershell

    ```wp-block-code
    .\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

    ```wp-block-code
    .\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:

    ```wp-block-code
    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:

    ```wp-block-code
    [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:

    ```wp-block-code
      [ERROR] No se pudo renombrar: <detalle del error>
    ```

Al finalizar, se muestra un resumen:

    ```wp-block-code
    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.

    ```wp-block-code
    <#
    .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
    }
    ```
