Cambio nombre archivos con PowerShell
Antecedentes
Dispongo de un archivo de material de referencia en una libreta de la aplicación Microsoft OneNote. Esta aplicación, organiza las libretas en carpetas y subcarpetas (son las múltiples secciones) en el sistema de archivos, donde cada una de ellas contiene un archivo para cada sección. En mi archivo tiene un tamaño y organización considerable (unos 357 archivos que ocupan unas 3 GB). Por motivos que no vienen al caso, tengo la necesidad de recuperar la copia de seguridad de este archivo, pero resulta que esta copia, en el nombre del archivo (y por lo tanto de la sección), tiene añadido «.one (fecha de copia)». Por ejemplo, un archivo puede ser:
Notas de reuniones.one (01-09-2013).one
Objetivo
Eliminar del nombre de todos los archivos la parte «.one (fecha de copia)». Siguiendo el ejemplo, dejar el archivo como:
Notas de reuniones.one
Opciones
1. Abrir cada carpeta, localizar el primer archivo, seleccionar cambiar nombre y aceptar. Repetir la operación hasta finalizar. Buff!!! Que trabajo.
2. Localizar por internet una aplicación gratuita que lo haga. Sinceramente, no tiene ganas de perder el tiempo buscando una aplicación que haga no sé qué, instalarla, probarla, desinstalarla, etc…
3. Automatizar la tarea mediante la PowerShell del propio sistema operativo. No debe dar miedo que no muerde.
Para saltar toda la teoría y ir al grano, ir directamente al final de la entrada.
Operativa PowerShell
Lo primero que se debe hacer es localizar la consola de PowerShell en el equipo:
- Microsoft Windows Vista y 7, está un poco escondida. Se debe ir al menú INICIO > Accesorios > Windows PowerShell.
- Microsoft Windows 8, desde el entorno ModernUI (el de mosaicos), escribir Power o bien buscarla en la carpeta de Herramientas Administrativas del Panel de Control.
Quizás sorprendre encontrar 4 iconos con el mismo nombre. Corresponden a las versiones de entorno de consola (Windows PowerShell) o con asistente (Windows PowerShell ISE) y si es en 32 (x86) o 64 bits (no indica nada). Seleccionar una de las opciones de consola (sin ISE, ya sea 32 o 64 bits). Se muestra una ventana del tipo MS-DOS de antes, es la consola y ¡no se le debe tener miedo!
Se escriben unas sencillas instrucciones:
Situarse en la carpeta raíz donde hay los datos. Se utiliza la instrucción CD. Recordar:
- c: ==> nombre unidad de disco seguido de : <== Cambia de disco, el disco duro, la unidad USB, el CD-Rom, etc…
- cd \ ==> cd (espacio) \ <== va a la raíz de la unidad de disco.
- cd nombrecarpeta, entra dentro de una carpeta. Si el nombre de la carpeta contiene espacios, este se debe poner entre comillas dobles.
En el ejemplo, la carpeta raíz se encuentra en la unidad C: dentro de la carpeta «cambio de nombres», las instrucciones a utilizar:
c: cd \ cd "cambio de nombres"
La primera instrucción nos la podríamos ahorrar ya que ya estamos en la unidad de disco donde hay la carpeta, la he puesto para mejor interpretación.
Para listar los archivos del directorio, se utiliza la instrucción Get-ChildItem. Escribir en esta consola:
get-childitem
Simplemente muestra el listado de carpetas y archivos que contiene la carpeta donde estamos. ¡Pero quiero ver todos los archivos de dentro de las carpetas! Añadir el parámetro -recurse.
get-childitem -recurse
Ahora salen un montón de cosas que llenan la pantalla y más. Acotamos el listado, PowerShell permite encadenar otras instrucciones con el símbolo | se hace con Alt Gr y sin dejar pulsar la tecla 1; en el teclado español).
Para ver el listado de archivos en una columna donde aparece sólo el nombre (Name), se utiliza la instrucción ft, equivale a Format-Table, seguida del nombre de los campos, separados por una coma, que se quieren ver. Por ejemplo, listar las carpetas que cuelgan de la raíz por fecha de modificación y nombre, la instrucción es:
get-childitem | ft LastWriteTime,Name
Para ver una columna con el nombre de todas las carpetas y archivos que cuelgan de la carpeta raíz:
get-childitem -recurse |ft name
En el listado aparecen el nombre de las carpetas y sólo quiero el nombre de los archivos de OneNote (tienen extensión .one). Toca filtrar esta lista, añadiendo el parámetro -filter y a continuación el texto a buscar utilizando el símbolo de comodín*. Ver todos los archivos con extensión .one (o .jpg, .docx, etc…)
get-childitem -recurse -filter "*.one" | ft name
Ver todos los archivos que dentro de su nombre contenga un espacio seguido de un paréntesis (se debe colocar el símbolo comodín al inicio y final del texto a buscar.
get-childitem -recurse -filter "* (*" | ft name
Ya tengo todos los archivos que les quiero cambiar el nombre, en este caso, eliminar el .one seguido de la fecha. Ojo que la extensión final .one debe mantenerse sinó la aplicación no sabrá que hacer con el archivo.
Para cambiar el nombre de una elemento, se utiliza la instrucción rename-item el nombre del archivo original seguido del parámetro -NewName con el nombre del archivo nuevo.
rename-item "c:\archivo original.one" -NewName "archivo nuevo.one"
Pero, la gracia es encadenar las instrucciones. Es decir, para cada archivo listado en la instrucción Get-ChildItem, coge sólo el nombre ($_.name), busca et texto (-replace) «.one (el 01-08-2013).one» y se sustituye por «.one», de esta manera se mantiene el nombre de la extensión.
get-childitem -recurse -filter "* (el 01-08-2013)*" | rename-item -NewName {$_.Name -replace ".one \(el 01-08-2013\).one",".one"} -WhatIf
Analizando la instrucción. Primero se buscan los archivos (get-childitem -recurse) que en su nombre contienen el texto (-filter) » (el 01-08-2013)», por lo tanto se introduce con los comodines al inicio y final (*).
Se encadena el resultado con la instrucción para cambiar el nombre (rename-item) en la cual ya no hace falta indicar el nombre original porque lo coge del listado de la primera instrucción. Pero si el nuevo nombre (-NewName) que se obtiene del nombre que proporciona la primera instrucción ($_.Name) en la que se tiene que cambiar la parte del texto (-replace) «.one (el 01-08-2013).one» por «.one». En este punto, fijarse que en la instrucción, antes del paréntesis va el símbolo \. No es una equivocación, sino que el paréntesis se considera un símbolo especial y dentro de una instrucción actúa como tal. Si lo que se pretende, como en este caso, es encontrar en el texto el paréntesis, se tiene que añadir el símbolo \ delante. También ver que estos parámetros van dentro de unas corcheas { } indicando que no es un simple parámetro sinó que se hacen varias operaciones (cambiar un texto por otros) para obtener un resultado.
Al final acaba con la instrucción -Whatif. Este parámetro se utiliza para ver que resultado produce la línea de comandos, pero SIN ejecutarlos, es decir, se vería que archivos cambia y con que nombe, pero realmente no se hace ninguna modificación.
Si el resultado es el esperado, ya se pueden realizar las modificaciones, eliminando el parámetro -WhatIf.
get-childitem -recurse -filter "* (el 01-08-2013)*" | rename-item -NewName {$_.Name -replace ".one \(el 01-08-2013\).one",".one"}
Se tendrá que modificar el filtro y el texto a cambiar para afinar, pero ya no son 357 archivos, ¡sino una línea¡
Similar Posts by The Author:
- Microsoft SQL Server con SMB3
- Microsoft SQL Server amb SMB3
- Containers en Linux
- Containers amb Linux
- Migrar el servidor de archivos a Windows Server 2019
- Migrar el servidor de fitxers a Windows Server 2019
- Puerta enlace a Azure en el Windows Admin Center
- Porta enllaç a Azure en el Windows Admin Center
- Hola mundo! WordPress 5 y Gutenberg
- Hola món! WordPress 5 i Gutenberg
Hola Josep:
Muchas gracias por el artículo. Me ha sido muy útil y, me ha ahorrado un montón de trabajo y tiempo. Lo he marcado en favoritos.
Desearía hacerte una consulta relacionada con cambio de nombre de archivos. Pienso que es un problema que tenemos muchos y, vamos a tener aún más en el futuro. ¿Cómo podría hacértela llegar?
Muchas gracias, de nuevo.