Desafío Powershell

7

Un amigo me desafió a hacer lo siguiente:

"Encuentre la forma más rápida y fácil de ordenar una lista de directorios por el ÚLTIMO carácter de los nombres de archivo".

Lo ha hecho en Linux usando lo siguiente:

ls | rev | sort | rev 

Me gustaría mostrarle la alternativa de PowerShell, pero apenas estoy empezando a aprender PowerShell y no puedo hacerlo. Entonces, estoy engañando y pidiendo tu ayuda.

Ricardo
fuente
1
En realidad, eso lo está ordenando no solo por el último personaje, sino por todos los caracteres siguientes. La respuesta de Sam Cogan a continuación es estrictamente por el último personaje e ignora los siguientes caracteres.
Sim
Antes de que alguien vote para migrar esta pregunta nuevamente, eche un vistazo a esto: meta.stackexchange.com/questions/32471/…
raven
Creo que este desafío es engañoso y, además, no es una comparación justa de Linux con PowerShell. Si rev solo clasificara el último personaje, sería justo. Además, lo que podría ser más justo sería pedirle a la gente que escriba bash o lo que sea para ordenar el último carácter, y no simplemente hacer: "ls | rev | sort | ls". Pero, sinceramente, ¿por qué alguien querría esta extraña función? Todavía me estoy rascando la cabeza, excepto quizás para tratar de convencer a alguien de que PowerShell puede ser tan compacto como sh, pero con una comparación de manzanas con naranjas.
Vista elíptica

Respuestas:

3

Desafortunadamente, Powershell no tiene un método reverso fácil y agradable, por lo que debe obtener la última letra de la cadena y ordenar por eso. Esta es una forma en que lo he hecho:

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

Como se ha señalado, esto se ordenará estrictamente solo por la última letra, mientras que la versión de Linux se ordenará por la última letra y luego las siguientes, por lo que puede haber una mejor manera de hacerlo, o puede que tenga que introducir algunos bucles si así lo quieres

Sam Cogan
fuente
Eso es genial. No es tan corto como la alternativa de Linux, pero sigue siendo bastante bueno.
Richard
También noté que esto solo se ordena por la última letra, a diferencia de la versión de Linux. Sin embargo, el desafío declaró "por el ÚLTIMO personaje", por lo que esta respuesta responde a la pregunta, incluso si las dos soluciones no son iguales.
Richard
Debido a cierta confusión, esta pregunta fue migrada a Stack Overflow y luego no migrada. Keith Hill en Desbordamiento de pila agregó la respuesta más corta ls | sort {"$ _" [- 1]}
Richard
9

Puedes probar esto:

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

No es tan corto como la versión unix, principalmente porque no hay una función String.Reverse () en .NET Framework. Básicamente, esto funciona diciéndole a sort 'ordenar calculando esta expresión en los argumentos de entrada'.


Ahora, si algún shell de Unix funciona mejor que

dir | sort -Property Length -Descending

para imprimir todos los archivos con el más grande primero, me interesaría verlo.

usuario25572
fuente
44
¿Qué tal 'ls -S'?
Bryan
¡Guauu! No sabía sobre este: D Nice one :)
AntonioCS
2

Estoy seguro de que alguien puede hacerlo mejor, pero aquí hay una forma que es totalmente compatible con Lynx. Tiene la ventaja de dejarle una revfunción de cadena reutilizable para su caja de herramientas, es decir, clasifica toda la cadena y no solo el último carácter:

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

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

Creo que el foreach aquí demuestra muy bien cómo las tuberías de PowerShell son matrices y no simplemente cadenas como en * nix.

Me tomó un tiempo darme cuenta de que tenía que usar solo $_y no $_.namedentro del segundo foreach. Así que aprendí algo sobre las variaciones en el contenido de la matriz de una tubería a la siguiente.

* El crédito por las agallas de mi función rev va a http://rosettacode.org/wiki/Reverse_a_string#PowerShell


Funciona como lynix:

  • dir | sort -Property @ {Expression = {$ n = $ _. Name.ToCharArray (); [Matriz] :: Reverso ($ n); [Cadena] :: Unir ("", $ n)}}

Algo así como trabajos como lynix, pero muy, muy lento:

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

No funciona como lynix, es decir , no puede ordenar todos los caracteres de los nombres de archivo; (solo ordena el último carácter de la cadena):

  • dir | sort {$ .name.Substring ($ .name.length-1)}
  • dir | ordenar {$ _. nombre [-1]}
  • ls | sort {$ _. Nombre [-1]}
  • ls | sort {"$ _" [- 1]}
  • ls -n | sort {$ _ [- 1]}
Vista elíptica
fuente
Esto podría mejorarse haciendo que la función rev acepte una matriz. Entonces podría eliminar forEach en el código, como lo llamaría la función. Puede agregar un par de cosas para que sea ls | rev | sort | revcompletamente válido por sí solo. :-)
Cory Knutson
1

La variante de Shay es mucho más corta que la respuesta aceptada al indexar en la cadena, pero incluso eso se puede mejorar. Puede acortarlo aún más excluyendo espacios innecesarios y utilizando un alias más corto:

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

También puede usar el -Nameargumento (abreviado) para Get-ChildItem:

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

que devolverá cadenas directamente.

Si realmente desea ordenar por la cadena inversa , entonces lo siguiente funciona (pero es lento):

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

Puede hacerlo más rápido si tiene un límite superior en la longitud del nombre del archivo.

Joey
fuente
Citando la pregunta: »Encuentre la forma más rápida y fácil de ordenar un listado de directorio por el ÚLTIMO carácter de los nombres de archivo.«. Solo necesita ordenar por el último personaje. Si la forma más fácil de hacerlo es invertir la cadena, que así sea, pero si la forma más fácil de hacerlo es simplemente ordenar por el último carácter, entonces esto también resuelve la tarea. La pregunta no era sobre "¿Cómo puedo hacer este fragmento de shell de Unix exactamente igual en PowerShell?".
Joey
Lo siento. Me equivoqué.
Vista elíptica
-1
ls|sort{"$_"[-1]}
juan
fuente