Bash a <(..)
pour la substitution de processus. Quel est l'équivalent de Powershell?
Je sais qu'il existe $(...)
, mais il renvoie une chaîne, tandis que <(..)
renvoie un fichier à partir duquel la commande externe peut lire, ce à quoi il s'attend.
Je ne recherche pas non plus une solution basée sur les tuyaux, mais quelque chose que je peux coller au milieu de la ligne de commande.
powershell
IttayD
la source
la source
Write-Output "The BITS service is $(Get-Service bits | select -ExpandProperty Stauts)"
pour obtenir le statut du service BITS sans le charger d'abord dans une variable. En ce qui concerne la substitution de processus, ce n'est pas exactement la même chose, mais cela pourrait toujours résoudre le problème auquel vous êtes confrontépsftp.exe
pour les transferts SFTP: son-b
option vous oblige à fournir des commandes à exécuter sur le serveur via un fichier , ce qui n'est pas pratique, si vous voulez simplement l'exécuter, disonsmget *
. Si PowerShell avait une substitution de processus, vous seriez en mesure de faire quelque chose commepsftp.exe -l user -p password somehost -b <( "mget *" )
.Réponses:
Cette réponse n'est PAS pour vous , si vous:
- rarement, voire jamais, avez besoin d'utiliser des CLI externes (ce qui vaut généralement la peine d'être recherché - les commandes natives de PowerShell jouent beaucoup mieux ensemble et n'ont pas besoin d'une telle fonctionnalité).
- ne connaissent pas la substitution de processus de Bash.
Cette réponse EST pour vous , si vous:
- utilisez fréquemment des CLI externes (que ce soit par habitude ou par manque de (bonnes) alternatives natives PowerShell), en particulier lors de l'écriture de scripts.
- sont habitués et apprécient ce que la substitution de processus de Bash peut faire.
- Mise à jour : Maintenant que PowerShell est également pris en charge sur les plates-formes Unix, cette fonctionnalité présente un intérêt croissant - voir cette demande de fonctionnalité sur GitHub, ce qui suggère que PowerShell implémente une fonctionnalité similaire à la substitution de processus.
Dans le monde Unix, dans Bash / Ksh / Zsh, une substitution de processus propose de traiter la sortie de commande comme s'il s'agissait d'un fichier temporaire qui se nettoie après lui-même; par exemple
cat <(echo 'hello')
, oùcat
voit la sortie de laecho
commande comme le chemin d'un fichier temporaire contenant la sortie de la commande .Bien que les commandes natives de PowerShell n'aient pas vraiment besoin d'une telle fonctionnalité, cela peut être pratique lorsque vous traitez avec des CLI externes .
Émuler la fonctionnalité dans PowerShell est lourd , mais peut en valoir la peine, si vous en avez souvent besoin.
Imaginez une fonction nommée
cf
qui accepte un bloc de script, exécute le bloc et écrit sa sortie dans un temp. fichier créé à la demande et retourne le temp. chemin du fichier ; par exemple:Il s'agit d'un exemple simple qui n'illustre pas bien la nécessité d'une telle fonctionnalité. Un scénario plus convaincant est peut-être l'utilisation des
psftp.exe
transferts SFTP: son utilisation par lots (automatisée) nécessite de fournir un fichier d' entrée contenant les commandes souhaitées, tandis que ces commandes peuvent facilement être créées sous forme de chaîne à la volée.Afin d'être aussi largement compatible avec les utilitaires externes que possible, le temp. fichier doit utiliser UTF-8 codage sans une nomenclature (marque d'ordre d' octet) par défaut, mais vous pouvez demander une nomenclature UTF-8 avec
-BOM
, le cas échéant.Malheureusement, l' aspect de nettoyage automatique des substitutions de processus ne peut pas être directement émulé, donc un appel de nettoyage explicite est nécessaire ; le nettoyage est effectué en appelant
cf
sans arguments :Pour une utilisation interactive , vous pouvez automatiser le nettoyage en ajoutant l'appel de nettoyage à votre
prompt
fonction comme suit (laprompt
fonction renvoie la chaîne d' invite , mais peut également être utilisée pour exécuter des commandes en arrière-plan chaque fois que l'invite est affichée, semblable à Bash's$PROMPT_COMMAND
variable); pour la disponibilité dans toute session interactive, ajoutez les éléments suivants ainsi que la définition decf
ci - dessous à votre profil PowerShell:Pour une utilisation dans les scripts , pour garantir que le nettoyage est effectué, le bloc qui utilise
cf
- potentiellement le script entier - doit être encapsulé dans un bloctry
/finally
, dans lequelcf
sans arguments est appelé pour le nettoyage:Voici la mise en œuvre : fonctions avancées
ConvertTo-TempFile
et son alias succinct,cf
:Remarque : L'utilisation de
New-Module
, qui nécessite PSv3 +, pour définir la fonction via un module dynamique garantit qu'il ne peut y avoir de conflits de variables entre les paramètres de fonction et les variables référencées à l'intérieur du bloc de script passé.Notez la possibilité de spécifier éventuellement un chemin de sortie [fichier] et / ou une extension de nom de fichier.
la source
psftp.exe
, c'est ce qui m'a poussé à l'écrire. Même s'il est préférable de tout faire en natif dans PowerShell, ce n'est pas toujours possible; l'appel de CLI externes à partir de PowerShell se produit et continuera de se produire; si vous vous retrouvez à plusieurs reprises avec des CLI qui nécessitent une entrée de fichier qui peut (plus) facilement être construite en mémoire / par une autre commande, la fonction de cette réponse peut vous faciliter la vie.Lorsqu'il n'est pas placé entre guillemets doubles,
$(...)
renvoie un objet PowerShell (ou plutôt, tout ce qui est retourné par le code inclus), évaluant d'abord le code inclus. Cela devrait convenir à vos besoins ("quelque chose que [je] peux coller au milieu de la ligne de commande"), en supposant que la ligne de commande est PowerShell.Vous pouvez le tester en canalisant différentes versions
Get-Member
, ou même en le sortant directement.Lorsqu'il est placé entre guillemets, comme vous l'avez remarqué, `" $ (...) "renverra simplement une chaîne.
De cette façon, si vous vouliez insérer, disons, le contenu d'un fichier directement sur une ligne, vous pourriez utiliser quelque chose comme:
la source
Get-Content <(Get-ChildItem)
Get-ChildItem | Get-Content
fonctionne pas parfaitement bien? Ou vous pourriez autrement essayerGet-Content (Get-ChildItem).FullName
pour le même effet? Vous pouvez aborder cela à partir d'une vue complètement influencée par une autre approche de script.