Trabajo con una gran colección de archivos de texto en su mayoría subdivididos por series, duplicándolos periódicamente desde un repositorio ascendente y volviendo a empaquetarlos usando un script de shell de una organización de origen ligeramente caótica en formas más ordenadas y compactas. Las fuentes se recopilan en directorios de archivos para cada serie de números desde unos pocos hasta cientos por conjunto, con una convención de nomenclatura orientada a los seres humanos que se remonta a los años 90 con este patrón general:
multi-word-series-name [- $ subsetnumber] - $ docnumber [. {txt, html, pdf}]
Cuando una serie puede o no tener subconjuntos, los subconjuntos se pueden numerar con números romanos o árabes, una serie puede comenzar con documentos numerados en ningún subconjunto y luego obtener un subconjunto con la etiqueta "II" o "2", y así sucesivamente . Estos nombres funcionan bien para las personas que los usan desde el Finder, que en la mayoría de los casos los ordena de manera humana y detecta que el nombre-II-1 viene después del nombre-6 y que el nombre-2 no viene después del nombre-19 . Debido a que mi reenvasado consiste en ensamblar la última versión de cada serie en archivos individuales en su orden humano-racional, utilizo un fragmento simple de AppleScript que usa el Finder para ordenar los nombres de los elementos en un directorio determinado. Esto produce resultados correctos, pero es espectacularmente ineficiente por razones que no entiendo. El AppleScript es:
on run argv
set op to ""
set upath to POSIX file argv as string
tell application "Finder"
set foo to every item of folder upath
set foo to sort foo by name
repeat with curfile in foo
set thisname to the name of curfile
set op to op & " " & thisname as string
end repeat
end tell
return op
end run
(Y no, no recuerdo por qué lo hice de esa manera. Lo escribí alrededor del 2008 y la mayoría odio AppleScript ...) Esto se compila en un script llamado "flist.scpt" y se ejecuta desde mi shell script con "osascript flist.scpt / ruta / a / series / carpeta /". El resultado de ejecutar ese script con un directorio que tiene 26 archivos es pegar la CPU por más de 2 minutos. A modo de comparación, 'ls' proporciona resultados ordenados léxicamente en la misma máquina (un iMac G5 que ejecuta Leopard ... no se ríe, es una máquina de utilidad) en 0.008s con el script masticando el mismo directorio en segundo plano .
Estoy tratando de deshacerme de ese AppleScript por completo, pero no he encontrado una manera de reproducir la lógica de clasificación del Finder fácilmente, es decir, al establecer una configuración regional o dar algunos argumentos complejos para "ordenar" que ordenen los nombres correctamente . Mi solución alternativa si no puedo encontrar algo enlatado para hacer esto sería reproducir la lógica del Finder yo mismo en una mezcla malvada de tipo, sed, awk y shell, pero me gustaría evitar eso si es posible. Si hay algo tonto en mi AppleScript que está causando el horrible rendimiento, arreglarlo sería casi tan bueno como un encantamiento mágico a 'ls' para que se parezca al Finder.
ACTUALIZACIÓN: ¡SOLUCIONADO! Primero probé el módulo Perl Sort :: Naturally, pero ordenó los nombres de los subconjuntos etiquetados antes de los miembros implícitos del subconjunto "I", que no es lo que quería. Así que seguí adelante y comencé a escribir mi primer script de Ruby, después de hackear un arreglo en la configuración de Leopard Ruby para hacer que la 'gema' funcionara en el mundo moderno e instalar la gema naturalsort. El script Ruby de reemplazo (llamado con un nombre de directorio como argumento) es:
#! /usr/bin/env ruby -rubygems -KU
# Largely cargo-culted from stackexchange response.
# I dunno what exactly the shebang line opts to ruby do. Probably pwn me.
# My first Ruby script ever. Don't laugh too hard.
require 'natural_sort' # gem install naturalsort
dname = ARGV[0]
input = Dir.entries(dname)
puts NaturalSort.naturalsort(input)
Las diferencias menores en la salida son que esto incluye el. y .. entradas y delimita las entradas por línea en lugar de con espacios, pero como se llama desde un script de shell que ya filtra algunos nombres especiales, estos son triviales de manejar.