Lavoro con una vasta raccolta di file per lo più suddivisi per serie, periodicamente specchiandoli da un repository upstream e riconfezionandoli utilizzando uno script di shell da un'organizzazione di origine leggermente caotica in forme più ordinate e compatte. Le fonti sono raccolte in directory di file per ciascuna numerazione di serie da una manciata a centinaia per set, con una convenzione di denominazione semi-ordinatamente orientata all'uomo risalente agli anni '90 con questo modello generale:
multi-word-series-nome [- $ subsetnumber] - [. {Txt, html, pdf}] $ docnumber
Dove una serie può o non può avere sottoinsiemi, i sottoinsiemi possono essere numerati con numeri romani o arabi, una serie può iniziare con documenti numerati in nessun sottoinsieme e successivamente ottenere un sottoinsieme etichettato "II" o "2", e così via . Questi nomi funzionano bene per le persone che li usano dal Finder, che nella maggior parte dei casi li ordina in modo sensato per l'uomo e rileva che il nome-II-1 arriva dopo il nome-6 e che il nome-2 non viene dopo il nome-19 . Poiché il mio riconfezionamento consiste nell'assemblare l'ultima versione di ogni serie in singoli file nel loro ordine razionale umano, io uso un semplice bit di AppleScript che usa il Finder per ordinare i nomi degli elementi in una determinata directory. Questo produce risultati corretti, ma è straordinariamente inefficiente per ragioni che non capisco. AppleScript è:
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
(E no, non ricordo perché l'ho fatto in quel modo. L'ho scritto intorno al 2008 e per lo più odio AppleScript ...) Questo è compilato in uno script chiamato "flist.scpt" ed eseguito dalla mia shell script con "osascript flist.scpt / percorso / alla / serie / cartella /". Il risultato dell'esecuzione di tale script con una directory contenente 26 file consiste nel pegging della CPU per oltre 2 minuti. Per confronto, 'ls' dà risultati ordinati lessicalmente sulla stessa macchina (un iMac G5 che gira Leopard ... non ride, è una macchina di utilità) in 0.008s con lo script che mastica la stessa directory in background .
Sto cercando di sbarazzarmi completamente di questo AppleScript, ma non ho trovato un modo per riprodurre facilmente la logica di ordinamento del Finder, cioè impostando una localizzazione o dando alcuni argomenti complessi a 'ordinare' che ordinerà correttamente i nomi . La mia soluzione alternativa, se non riesco a trovare qualcosa in scatola per farlo, sarà quella di riprodurre io stesso la logica del Finder in un mix malvagio di sorta, sed, awk e shell, ma vorrei davvero evitarlo, se possibile. Se c'è qualcosa di sciocco sul mio AppleScript che sta causando la terribile performance, il fixing sarebbe quasi buono come un incantesimo magico a "ls" per renderlo simile al Finder.
UPDATE: SOLVED! Ho provato per la prima volta il modulo Perl Sort :: Naturally, ma ha ordinato nomi di sottoinsiemi etichettati prima dei sottotitoli impliciti "I", che non è quello che volevo. Così sono andato avanti e mi sono tuffato a scrivere il mio primo script in Ruby, dopo aver hackerato una correzione nella configurazione di Leopard Ruby per far funzionare "gemma" nel mondo moderno e installare la gemma naturalsort. Lo script di sostituzione Ruby (chiamato con un nome di directory come argomento) è:
#! /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)
Le piccole differenze nell'output sono che questo include il. e .. immette e delimita le voci per riga anziché con spazi, ma poiché questo viene chiamato da uno script di shell che già esclude alcuni nomi speciali, questi sono banali da gestire.