Défi PowerShell


7

Un ami m'a demandé de faire ce qui suit:

"Trouvez le moyen le plus rapide et le plus simple de trier une liste de répertoires en fonction du DERNIER caractère des noms de fichiers."

Il l'a fait sur Linux en utilisant ce qui suit:

ls | rev | sort | rev 

Je voudrais lui montrer l'alternative PowerShell, mais je commence à peine à apprendre PowerShell et je ne peux pas le faire. Alors je triche et je demande votre aide.


1
En fait, cela le trie non seulement par le dernier caractère, mais par tous les caractères suivants. La réponse de Sam Cogan ci-dessous est strictement par le dernier caractère et ignore tous les caractères suivants.
Sim

Avant que quiconque vote pour migrer à nouveau cette question, jetez un œil à ceci: meta.stackexchange.com/questions/32471/…
raven

Je pense que ce défi est trompeur et en outre pas une comparaison équitable de Linux avec PowerShell. Si rev ne triait que le dernier caractère, ce serait juste. De plus, ce qui pourrait être plus juste serait de demander également aux gens d'écrire bash ou autre pour ne trier que le dernier caractère, et pas simplement: "ls | rev | sort | ls". Mais honnêtement, pourquoi quelqu'un voudrait cette fonction étrange, je me gratte toujours la tête, sauf peut-être pour essayer de convaincre quelqu'un que PowerShell peut être aussi compact que sh, mais avec une comparaison des pommes et des oranges?
Vue elliptique le

Réponses:


3

Malheureusement, Powershell n'a pas de méthode inverse facile et agréable, vous devez donc obtenir la dernière lettre de la chaîne et trier par cela. Voici une façon de procéder:

dir| sort {$_.name.Substring($_.name.length-1)}

Comme cela a été souligné, cela triera strictement par la dernière lettre uniquement, alors que moi, la version Linux triera par la dernière et ensuite les lettres suivantes, donc il peut y avoir une meilleure façon de le faire, ou vous devrez peut-être introduire une boucle si vous le voulez comme ça.


C'est génial. Pas aussi court que l'alternative Linux, mais tout de même assez bon.
Richard

J'ai également remarqué que cela ne trie que par la dernière lettre, contrairement à la version linux. Cependant le défi posé "par le DERNIER caractère" donc cette réponse répond à la question, même si les deux solutions ne sont pas égales.
Richard

En raison d'une certaine confusion, cette question a été migrée vers Stack Overflow, puis non migrée. Keith Hill sur Débordement de pile a ajouté la réponse la plus courte ls | sort {"$ _" [- 1]}
Richard


2
dir | sort -Property @{Expression ={$n = $_.Name.ToCharArray(); [Array]::Reverse($n);[String]::Join("",$n)}}

Pas aussi court que la version Unix, principalement parce qu'il n'y a pas de fonction String.Reverse () dans le .NET Framework. Fondamentalement, cela fonctionne en disant tri «tri en calculant cette expression sur les arguments d'entrée».


Maintenant, si un shell Unix fait mieux que

dir | sort -Property Length -Descending

pour imprimer tous les fichiers avec le plus gros en premier, je serais intéressé de le voir.


4
Que diriez-vous de «ls -S»?
Bryan

Hou la la! Je ne savais pas à propos de celui-ci: D Nice one :)
AntonioCS

2

Je suis sûr que quelqu'un peut faire mieux, mais voici une façon qui est entièrement compatible avec lynix. Il a l'avantage de vous laisser une revfonction de chaîne réutilisable pour votre boîte à outils, c'est-à-dire qu'il trie la chaîne entière et pas seulement le dernier caractère:

function rev ($s) {return -join ($s[$s.Length..0])}

dir | foreach{rev($_.name)} | sort | foreach{rev($_)}

Je pense que le foreach ici montre bien comment les tuyaux PowerShell sont des tableaux et non pas simplement des chaînes comme dans * nix.

Il m'a fallu un peu de temps pour réaliser que je devais utiliser uniquement $_et non $_.nameà l'intérieur du 2ème foreach. J'ai donc appris quelque chose sur les variations du contenu du tableau d'un canal à l'autre.

* Le crédit pour le courage de ma fonction rev va à http://rosettacode.org/wiki/Reverse_a_string#PowerShell


Fonctionne comme lynix:

  • dir | sort -Property @ {Expression = {$ n = $ _. Name.ToCharArray (); [Tableau] :: Reverse ($ n); [String] :: Join ("", $ n)}}

Des œuvres comme Lynx, mais très, très lentes:

  • ls -n | sort {$ _ [3e3..0]}

Ne fonctionne pas comme lynix, c'est-à-dire ne trie pas tous les caractères des noms de fichiers; (trie uniquement le tout dernier caractère de la chaîne):

  • dir | sort {$ .name.Substring ($ .name.length-1)}
  • dir | trier {$ _. nom [-1]}
  • ls | sort {$ _. Nom [-1]}
  • ls | sort {"$ _" [- 1]}
  • ls -n | sort {$ _ [- 1]}

Cela pourrait être amélioré en faisant accepter à la fonction rev un tableau. Ensuite, vous pouvez éliminer forEach dans le code, comme la fonction l'appellerait. Vous pouvez ajouter quelques éléments pour que le tout soit ls | rev | sort | reventièrement valide. :-)
Cory Knutson

1

La variante de Shay est beaucoup plus courte que la réponse acceptée en l'indexant dans la chaîne mais même cela peut être amélioré. Vous pouvez le raccourcir encore plus en excluant les espaces inutiles et en utilisant un alias plus court:

ls|sort{$_.Name[-1]}

Vous pouvez également utiliser l' -Nameargument (abrégé) pour Get-ChildItem:

ls -n|sort{$_[-1]}

qui renverra directement les chaînes.

Si vous voulez vraiment trier par la chaîne inverse , alors les travaux suivants (mais sont lents):

ls -n|sort{$_[3e3..0]}

Vous pouvez l'accélérer si vous avez une limite supérieure sur la longueur du nom de fichier.


Citant la question: »Trouvez le moyen le plus rapide et le plus simple de trier une liste de répertoires par le DERNIER caractère des noms de fichiers.«. Il suffit de trier par le dernier caractère. Si la façon la plus simple de le faire est d'inverser la chaîne, qu'il en soit ainsi, mais si la façon la plus simple de le faire est de simplement trier par le dernier caractère, cela résout également la tâche. La question ne portait pas sur «Comment puis-je faire exactement cet extrait de shell Unix de la même manière dans PowerShell?».
Joey

Désolé. Je me suis trompé.
Vue elliptique du

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.