Gestión avanzada de archivos
Introducción
Es frecuente al hacer scripting (sin importar el lenguaje), utilizar uno o varios archivos. La mayoría de las veces, se trata de archivos planos. En distribuciones Unix/Linux, esto es más que común. En las primeras versiones de PowerShell, ciertas características eran seriamente escasas en las tareas cotidianas. No era raro tener que realizar una serie de funciones invocando directamente objetos del .NET Framework. Afortunadamente, la versión 5.0 de PowerShell trae comandos nativos para gestionar mejor los archivos y todo lo que conllevan.
En este capítulo, veremos las novedades de PowerShell 5.1 en cuanto a la gestión de archivos. Explicaremos cómo comprimir y descomprimir fácilmente un archivo. También veremos cómo gestionar enlaces simbólicos en archivos y carpetas, algo que antes no era fácil. También veremos cómo crear archivos temporales cuando se utilizan scripts. Por último, veremos cómo utilizar sesiones PowerShell para transferir un conjunto de archivos y editar un archivo remoto utilizando PowerShell ISE.
Gestión de archivos
Los archivos ZIP son habituales cuando empiezas a hacer scripts. Los archivos de registro se agrupan en un archivo para ahorrar espacio. O exportas un gran número de archivos, y para que sea más fácil recuperarlos, los colocas en un archivo. Esto es lo que será visto ahora. A continuación, veremos cómo se realizaba este procedimiento en versiones de PowerShell anteriores a la 5.1, para apreciar la simplicidad de los nuevos comandos.
1. Compress-Archive
El comando utilizado para crear archivos ZIP a partir de una carpeta o un conjunto de archivos es Compress-Archive. Es bastante sencillo de utilizar y cuenta con pocos parámetros:
Parámetro |
Descripción |
Path [string[]] |
Indica la ruta a la carpeta o los archivos que se van a comprimir. Este parámetro acepta wildcards. |
DestinationPath [string] |
Indica la ruta al archivo ZIP. Si se omite la extensión .ZIP, el comando la añade automáticamente. |
Update [switch] |
Indica si los archivos deben añadirse a un archivo existente. En caso contrario, se sobrescribirá el archivo. |
CompressLevel <Optimal, NoCompression, Fastest> |
Indica el nivel de compresión del archivo. El valor por defecto es Optimal. |
Force [switch] |
Indica si se debe forzar la ejecución del comando, para evitar pedir confirmación al usuario. |
Sin embargo, la API .NET utilizada por el comando Compress-Archive impone una restricción al archivo. El tamaño máximo de un archivo que se puede comprimir está limitado a 2 GB.
Supongamos que tenemos una carpeta llamada MyFolderLogs en C:\Temp. Contiene un gran número de registros que queremos comprimir en el archivo con fecha y hora C:\Temp\ArchiveLogs<yyyy-MM-dd-hhmm>.ZIP.
Ejecutamos los siguientes comandos:
PS > $DateTime = Get-Date -Format 'yyyy-MM-dd-hhmm'
PS > Compress-Archive -Path C:\Temp\MyFolderLogs `
-DestinationPath C:\Temp\ArchiveLogs$DateTime
PS > Get-ChildItem -Path...
Enlace simbólico
Al igual que con los archivos, inicialmente no existía una forma nativa de gestionar enlaces simbólicos. Pero desde la versión 5 de PowerShell, las cosas han cambiado. El comando New-Item acepta el término SymbolicLink en el parámetro -ItemType para crear enlaces simbólicos en carpetas o archivos.
1. Archivos
Aunque pueda parecer extraño, para crear un enlace simbólico con el comando New-Item, es necesario contar con privilegios elevados.
Por tanto, las siguientes acciones se lanzan desde una consola PowerShell ejecutada como administrador.
Creación de un enlace simbólico
En este ejemplo, creamos un enlace a un archivo de registro:
PS > New-Item -ItemType SymbolicLink -Path C:\Temp `
-Name log1.lnk -value C:\Temp\MyFolderLogs\log1.log
Directorio : C:\temp\.
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---l 23/03/2018 19:44 0 log1.lnk
El parámetro -ItemType indica que se trata de un enlace simbólico. El parámetro -Path indica la ubicación donde debe crearse el enlace simbólico. El valor del parámetro -Name es el nombre del enlace. Por último, el parámetro -Value indica la ruta del archivo al que apunta el enlace simbólico. Puede ser una ruta completa o una ruta relativa.
La propiedad Mode tiene un elemento adicional en el caso de un enlace simbólico. El campo termina con una l, a diferencia de un archivo estándar, que tiene un guión (-).
Eliminación de un enlace simbólico
La eliminación de un enlace simbólico en un archivo se realiza del mismo modo que la eliminación de un archivo estándar. Se utiliza el comando Remove-Item :
PS > Remove-item -Path C:\Temp\log1.lnk
Veremos que no es tan fácil eliminar...
Archivo temporal
Cuando se escribe un script, puede que se necesite escribir información temporalmente para procesarla más tarde en el script. Puede resultar tedioso gestionar este tipo de situaciones: se crea un archivo temporal con un nombre aleatorio y se elimina este archivo al final del script. Desde la versión 5 de PowerShell, se puede utilizar el comando New-TemporaryFile para crear un archivo temporal almacenado en $env:temp. Esta es una carpeta temporal en la carpeta AppData del usuario actual. El nombre del archivo temporal tiene el siguiente formato: temp<XXXX>.tmp. Los caracteres X son hexadecimales y generados aleatoriamente.
El comando New-TemporaryFile no tiene parámetros especiales. La simple llamada al comando genera un archivo, y la salida del comando es el objeto de este archivo.
Ejemplo
PS > New-TemporaryFile
Directorio : C:\Users\Nicolas\AppData\Local\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 23/03/2018 23:27 0...
Edición de archivos remotos
A menudo es tedioso tener que editar archivos en sistemas remotos. Normalmente, se conecta al ordenador de forma remota y se editan los archivos utilizando el editor de archivos disponible. La otra opción es acceder al recurso compartido administrativo de la máquina y editar los archivos con su editor favorito.
Gracias a la versión 5.1 de PowerShell, ahora se dispone de un nuevo método. Ahora es posible editar un archivo de texto remoto mediante una sesión interactiva en PowerShell ISE. El archivo se edita utilizando la utilidad PSEdit.exe. Debe utilizarse en una sesión interactiva desde PowerShell ISE. Para obtener más información sobre las sesiones remotas de PowerShell, consulte el capítulo Gestión remota avanzada.
Para entrar en la sesión interactiva, utilice el comando Enter-PSSession. Con este comando, puede iniciar desde una sesión existente utilizando el parámetro -PSSession, o crear una nueva utilizando el parámetro -ComputerName.
Desde PowerShell 5.1, es posible crear sesiones en una máquina virtual en un hipervisor Hyper-V. Se utilizan los parámetros -VMName o -VMId. No olvide introducir las credenciales si el hipervisor se encuentra en un contexto diferente al de la máquina virtual (WorkGroup/Domaine Active Directory). Es posible editar archivos remotos utilizando PSEDIT a través de una sesión PowerShell...
Copia de archivos a través de una sesión PowerShell
Una de las características que faltaban en las sesiones remotas de PowerShell era la capacidad de transferir uno o más archivos de forma sencilla y segura. Esto era algo que podía hacer el protocolo SSH de Linux. Por ello, los diseñadores de PowerShell han mejorado esta capacidad, y la versión 5.1 incluye esta funcionalidad de forma nativa.
El comando Copy-Item tiene dos nuevos parámetros:
-
FromSession: para indicar que el archivo de origen se encuentra en el sistema remoto y que el destino está en el sistema local.
-
ToSession: para indicar que el archivo de origen se encuentra en el sistema local y que el destino es el sistema remoto.
Estos parámetros son mutuamente excluyentes, por lo que no pueden usarse simultáneamente en un mismo comando. Aceptan objetos de tipo PSSessioncreados mediante el comando New-PSession (véase el capítulo Gestión remota avanzada).
Creamos un archivo PowerShell :
PS > $Session = New-PSSession -ComputerName SRVDC02
Copiamos un archivo del host local al sistema remoto. Para obtener más detalles durante la operación, se recomienda añadir el parámetro -Verbose:
PS > Copy-Item -Path $Home\Documents\configue.txt `
-Destination C:\Temp\configue.txt -ToSession $Session -Verbose
COMENTARIOS: Operación "Copiar el archivo"...
Conversión de un archivo plano en un objeto
En el mundo Unix/Linux, no es raro ver archivos de texto formateados de una manera muy específica. Se trata de archivos de configuración o archivos de logs. Estos archivos se pueden procesar en grandes cantidades, con fines de reporting, para comprobar la coherencia de los datos o para exportar la configuración de un sistema a otro (por ejemplo, DHCP en Windows a DHCP en Linux). Pero procesar estos archivos puede ser tedioso. Se acaba utilizando un gran número de expresiones regulares, lo que puede resultar un poco desalentador si no se practica. Para facilitar las cosas, se ha introducido un nuevo comando en PowerShell V5. Se trata de ConvertFrom-String. Se puede utilizar de dos maneras. La primera es básica y es muy similar a los comandos Import-Csv y Convert-Csv. La segunda es más compleja. Se basa en el framework FlashExtract desarrollado por una unidad del centro de investigación de Microsoft. Mediante ejemplos, FlashExtract extrae datos de un archivo semiestructurado. El resultado de la extracción se representa en forma de objeto. En primer lugar, presentaremos algunos casos del método básico y, a continuación, nos centraremos en el método complejo. Una vez que domine el método complejo, podrá abandonar (parcialmente) el uso de expresiones regulares.
1. Modo básico
En su forma más simple, ConvertFrom-String separa las cadenas utilizando los espacios como delimitadores y genera nombres de propiedades aleatorios.
Ejemplo
PS > 'PowerShell está en Linux' | ConvertFrom-String
P1 P2 P3 P4
-- -- -- --
PowerShell está en Linux
Si se hubiera introducido una quinta palabra, la visualización habría cambiado al formato de lista. Aquí se aplica el formato predeterminado (véase el capítulo Objetos personalizados y tipos estándar).
Se pueden procesar varias cadenas de caracteres:
PS > $Here = 'PowerShell está en Linux','Pero también en MacOs'.
PS > $Here | ConvertFrom-String
P1 P2 P3 P4
-- -- -- --
PowerShell está en Linux
Pero también en MacOs
Al igual que con ConvertFrom-Csv, el delimitador puede cambiarse utilizando el parámetro -Delimiter:
PS > $Here | ConvertFrom-String -Delimiter 's'...