Cambio nombre archivos con PowerShell

17 septiembre 2016
Josep Ma Solanes 1

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.

PowerShell1

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!

PowerShell7

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.

PowerShell6

Para listar los archivos del directorio, se utiliza la instrucción Get-ChildItem. Escribir en esta consola:

get-childitem

PowerShell5

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

PowerShell4

 

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

PowerShell3

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.

PowerShell2

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:

 

Un comentari per a
“Cambio nombre archivos con PowerShell”

  1. 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.

     
Els comentaris estan tancats.