Ejecutar PowerShell desde el Símbolo del sistema
Las tareas difíciles de realizar solo con el Símbolo del sistema, como comprimir archivos ZIP, convertir formatos de fecha o analizar JSON, se pueden resolver llamando a PowerShell desde el Símbolo del sistema. Con el comando powershell también puede incorporar procesos de PowerShell dentro de un archivo por lotes.
Este artículo explica el uso básico del comando powershell y cómo manejar los puntos que más problemas dan: las comillas, el escape de caracteres y la directiva de ejecución.
Sintaxis básica del comando powershell
powershell [-NoProfile] [-ExecutionPolicy <directiva>] -Command "<comando>"
powershell [-NoProfile] [-ExecutionPolicy <directiva>] -File <ruta_del_script> [argumentos...]
Si escribe solo powershell en el Símbolo del sistema, el indicador cambia a PS C:\> y entra en el modo interactivo de PowerShell. Para volver, escriba exit.
El comando powershell incluido de serie en Windows es Windows PowerShell 5.1. PowerShell 7 y las versiones posteriores, que se instalan por separado, se inician con el comando pwsh. Las opciones de este artículo funcionan igual en ambos.
Ejecutar un solo comando (-Command)
Si pasa un comando a -Command, vuelve al Símbolo del sistema después de ejecutarlo.
powershell -Command "Get-Date"
-Command se puede omitir (powershell "Get-Date"). Sin embargo, la interpretación de los argumentos se vuelve más difícil de seguir, por lo que se recomienda indicarlo de forma explícita.
Los comandos de PowerShell (cmdlets) siguen por lo general el formato “verbo-sustantivo”, como Get-ChildItem. Por ejemplo, para mostrar solo los 5 archivos modificados más recientemente de la carpeta actual, del más nuevo al más antiguo, haga lo siguiente.
powershell -NoProfile -Command "Get-ChildItem | Sort-Object LastWriteTime -Descending | Select-Object -First 5 Name, LastWriteTime"
Como | está dentro de las comillas dobles ", se procesa como una canalización de PowerShell y no del Símbolo del sistema.
Opciones de uso frecuente
| Opción | Descripción |
|---|---|
-Command | Ejecuta la cadena indicada como un comando de PowerShell |
-File | Ejecuta el script .ps1 indicado |
-NoProfile | No carga el perfil (el script de configuración de inicio). Inicia más rápido y hay menos diferencias entre entornos |
-NonInteractive | No espera entrada del usuario. Las operaciones que requieren confirmación producen un error |
-ExecutionPolicy <directiva> | Establece la directiva de ejecución solo para este proceso (por ejemplo, Bypass) |
-NoExit | Mantiene PowerShell abierto después de ejecutar el comando |
-EncodedCommand | Pasa un comando codificado en Base64 a partir de una cadena UTF-16LE (para evitar problemas con las comillas) |
Al llamar desde un archivo por lotes, conviene añadir -NoProfile para mayor estabilidad.
Ejecutar un archivo de script (-File)
Cuando el proceso se alarga, es más seguro separar el código de PowerShell en un archivo .ps1 y ejecutarlo con -File.
param([string]$Name = 'World')
Write-Host "Hello, $Name!"
powershell -NoProfile -ExecutionPolicy Bypass -File .\hello.ps1 -Name Taro
Cuando aparece un error de directiva de ejecución
Si al intentar ejecutar un archivo .ps1 aparece un error como “la ejecución de scripts está deshabilitada en este sistema”, la causa es la directiva de ejecución. Al añadir -ExecutionPolicy Bypass, se omite la directiva solo para ese proceso. La configuración de todo el sistema no cambia.
La directiva de ejecución restringe la ejecución de archivos .ps1. La cadena que se pasa con -Command no está sujeta en sí misma a la directiva de ejecución. Sin embargo, si llama a un .ps1 desde dentro de -Command, la directiva se aplica a ese script (y si no añade -NoProfile, la carga del perfil también puede producir un error). Además, use -ExecutionPolicy Bypass solo con scripts de confianza. Si el administrador de su organización establece la directiva de ejecución mediante directivas de grupo, no puede sobrescribirla con -ExecutionPolicy.
Manejo de comillas y caracteres especiales
Como la línea de comandos pasa por el Símbolo del sistema y por PowerShell, hay que tener cuidado con los caracteres especiales.
| Carácter | Aspecto a tener en cuenta en el Símbolo del sistema (cmd) | Solución |
|---|---|---|
" | Se usa para encerrar todo el contenido de -Command | Es más fácil usar ' (comillas simples) en el interior |
% | En un archivo por lotes se expande como variable | Escriba %% |
|, &, > | cmd los interpreta si están fuera de las comillas dobles | Colóquelos dentro de comillas dobles o escápelos con ^ |
$ | No tiene un significado especial en cmd. Se trata como variable de PowerShell | Se puede escribir tal cual |
! | Desaparece si la expansión retardada está habilitada | Ejecute con la expansión retardada deshabilitada |
La solución más sencilla es encerrar todo el comando entre " y usar ' para los literales de cadena del interior.
powershell -NoProfile -Command "Write-Host 'Hola' ; (Get-Date).ToString('yyyy-MM-dd')"
Si necesita usar " en el interior, puede pasarlas escribiendo \".
powershell -NoProfile -Command "Write-Host \"Hora actual: $((Get-Date).ToString('HH:mm'))\""
Cuando el escape se acumule en dos o tres niveles y resulte difícil de leer, no se empeñe con -Command. Pase el código a un archivo .ps1 y ejecútelo con -File. Además, será más fácil de mantener.
Usar el resultado en un archivo por lotes
Guardar la salida en una variable
Con for /f, puede capturar la salida de PowerShell en una variable del archivo por lotes. Dentro de un archivo por lotes, escriba % como %%.
@echo off
for /f "usebackq delims=" %%d in (`powershell -NoProfile -Command "Get-Date -Format yyyyMMdd_HHmmss"`) do set TIMESTAMP=%%d
echo %TIMESTAMP%
Si añade usebackq a for /f, puede encerrar el comando entre acentos graves (`). Aunque use comillas simples ' en el lado de PowerShell, no entran en conflicto con la sintaxis de for /f.
El formato de %date% en el Símbolo del sistema cambia según la configuración regional, pero Get-Date -Format de PowerShell devuelve una cadena con el mismo formato independientemente de esa configuración.
Obtener el código de salida
Al ejecutar con -Command, ERRORLEVEL recibe 0 si el último comando se ejecutó correctamente y 1 si falló. Es posible que el código de salida de un programa externo no se transmita tal cual, así que cuando quiera informarlo con seguridad o controlarlo con precisión, especifique el código de salida con exit.
powershell -NoProfile -Command "if (Test-Path 'C:\data') { exit 0 } else { exit 2 }"
echo %ERRORLEVEL%
Un script ejecutado con -File también puede devolver un código de salida con exit <número>.
Ejemplo práctico: comprimir y extraer archivos ZIP
Con Compress-Archive y Expand-Archive, puede trabajar con archivos ZIP desde el Símbolo del sistema.
powershell -NoProfile -Command "Compress-Archive -Path 'C:\data\*' -DestinationPath 'C:\backup\data.zip' -Force"
powershell -NoProfile -Command "Expand-Archive -Path 'C:\backup\data.zip' -DestinationPath 'C:\restore' -Force"
El -Force de Compress-Archive sobrescribe un archivo ZIP existente, y el -Force de Expand-Archive sobrescribe los archivos con el mismo nombre que haya en el destino.
Ejemplo práctico: reemplazar texto
Reemplazar cadenas dentro de un archivo es difícil solo con el Símbolo del sistema, pero sencillo con PowerShell.
powershell -NoProfile -Command "(Get-Content 'a.txt' -Raw -Encoding UTF8) -replace 'foo','bar' | Set-Content 'b.txt' -Encoding UTF8"
En Windows PowerShell 5.1, Set-Content escribe con la página de códigos predeterminada del sistema cuando se omite -Encoding (por ejemplo, Windows-1252 en un sistema en español de Europa occidental, o una página de códigos de la familia Shift_JIS en un sistema japonés). Para evitar caracteres ilegibles, especifique -Encoding de forma explícita tanto al leer como al escribir. Tenga en cuenta que -Encoding UTF8 en 5.1 escribe con BOM (PowerShell 7 escribe sin BOM). Además, si guarda el propio archivo por lotes en UTF-8, el texto que no sea ASCII (como los caracteres con tilde o los japoneses) dentro de -Command puede mostrarse con caracteres ilegibles. Para más información sobre la codificación de caracteres, consulte los artículos relacionados.
Resumen
| Objetivo | Comando |
|---|---|
| Iniciar PowerShell en modo interactivo | powershell |
| Ejecutar un solo comando | powershell -NoProfile -Command "..." |
Ejecutar un script .ps1 | powershell -NoProfile -ExecutionPolicy Bypass -File a.ps1 |
| Usar PowerShell 7 | pwsh -NoProfile -Command "..." |
| Guardar la salida en una variable | for /f "delims=" %%x in ('powershell ...') do set VAR=%%x |
| Obtener el código de salida | %ERRORLEVEL% |