subir - Listado de todos los archivos en una carpeta usando JavaScript para automatización en Yosemite
read file javascript (3)
Al igual que Leopard''s Scripting Bridge , JXA rompe intencionalmente todo tipo de cosas que funcionan perfectamente en AppleScript. Aquí está la traducción de su comando original de AppleScript a la sintaxis de JXA:
//tell application "System Events" to name of items in folder "/usr"
Application(''System Events'').folders.byName(''/usr'').items.name()
La versión AS funciona perfectamente, pero el equivalente JXA simplemente arroja un Error -1700: Can''t convert types.
completamente sin sentido Error -1700: Can''t convert types.
JXA parece funcionar si escribe diskItems
lugar de items
:
Application(''System Events'').folders.byName(''/usr'').diskItems.name()
// --> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
lo que sugiere que JXA se entrega a la misma "astucia" interna que hace que SB rompa tantas aplicaciones. (Tenga en cuenta que encontré numerosos defectos de diseño en pruebas anteriores, pero renuncié a informarlos una vez que quedó claro que los desarrolladores de AS solo se preocuparon por imponer su propia ideología personal y sus prejuicios a los demás, las capacidades paralizadas y la incompatibilidad de la compatibilidad).
A modo de comparación, aquí está el prototipo de JavaScriptOSA (JOSA) que reuní rápidamente para la referencia de los desarrolladores de JXA hace unos meses (inmediatamente lo ignoraron, natch):
app(''System Events'').folders.named(''/usr'').items.name()
// -> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
(Aunque no está totalmente terminado o probado, JOSA todavía funciona mucho mejor que JXA, está mejor documentado e incluso incluye una herramienta de auto-traducción para convertir comandos AS a sintaxis JS. Desafortunadamente, debido a que Apple ha dejado o desaprobó el AEM, CM , PM, y OSA Carbon APIs, no puedo recomendarlo para uso de producción, es puramente para fines de comparación).
Similar:
set myPath to POSIX file "/usr"
tell application "System Events" to name of every disk item of folder named myPath
--> {"bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"}
myPath = Path(''/usr'')
Application(''System Events'').folders.byName(myPath).diskItems.name()
// Error -1728: Can''t get object.
var myPath = Path(''/usr'')
app(''System Events'').folders.named(myPath).diskItems.name()
// --> ["bin", "lib", "libexec", "local", "sbin", "share", "standalone", "X11", "X11R6"]
Puede solucionar ese caso particular convirtiendo el objeto Path en una cadena y usando eso:
myPath = Path(''/usr'')
Application(''System Events'').folders.byName(myPath.toString()).diskItems.name()
Aunque esa solución no necesariamente ayudará en otras situaciones; por ejemplo, falla en Finder porque Finder no entiende las cadenas de ruta de estilo POSIX, y no hay forma de obtener una cadena de ruta de estilo HFS (que Finder sí entiende) de un objeto Ruta JXA:
set myPath to POSIX file "/usr"
tell application "Finder" to name of every item of item myPath
--> {"X11", "X11R6", "bin", "lib", "libexec", "local", "sbin", "share", "standalone"}
myPath = Path(''/usr'')
Application(''Finder'').folders.byName(myPath.toString()).items.name()
// Error -1728: Can''t get object.
Y así continúa. (Por ejemplo, prueba el soporte de JXA para formularios de referencia de rango, filtro, relativo e inserción; está particularmente podrido).
Estoy tratando de trasladar algunos antiguos Applescript a la nueva sintaxis de JavaScript.
Algunas cosas parecen ser bastante sencillas, así que:
tell application "System Events" to keystroke "t" using command down
se convierte en:
System = Application(''System Events'');
System.keystroke("t", {using: "command down"})
Sin embargo, no puedo por la vida de mí averiguar cómo enumerar los archivos en una ubicación específica. En AppleScript, para devolverme una lista de los archivos en el directorio /usr
, harías:
tell application "System Events" to set fileList to name of items in folder "/usr"
-- > {"bin", "include", "lib", "libexec", "local", "sbin", "share", "standalone", "X11"}
Sin embargo, no puedo por la vida de mí averiguar cómo hacerlo en Javascript.
System = Application(''System Events'')
myPath = Path("/usr")
fileList = System.items(myPath)
-- > message not understood
fileList = System.folder(myPath)
-- > message not understood
fileList = System.diskItems(myPath)
-- > []
fileList = System.diskItems({at:myPath)
-- > []
También probé muchas otras combinaciones, pero no tuve suerte. ¿Algunas ideas?
El enfoque de "System Events"
ciertamente tiene el mérito de la simplicidad, pero resulta que el uso de $.NSFileManager
(ahora directamente disponible para secuencias de comandos) ofrece un rendimiento notablemente más rápido.
En mi sistema, comenzando por la comparación con
var strPath = ''/usr'';
var appSys = Application(''System Events''),
lstHarvest = appSys.folders.byName(strPath).diskItems.name();
Una prueba rápida con unos pocos miles de iteraciones sugiere que podemos acelerarlo constantemente en un moderado 40% con este enfoque ligeramente barroco:
var strPath = ''/usr'';
var fm = $.NSFileManager.defaultManager,
oURL = $.NSURL.fileURLWithPathIsDirectory(strPath, true),
lstFiles = ObjC.unwrap(
fm.contentsOfDirectoryAtURLIncludingPropertiesForKeysOptionsError(
oURL, [], 1 << 2, null
)
),
lstHarvest = [];
lstFiles.forEach(function (oItem) {
lstHarvest.push(
ObjC.unwrap(oItem.path)
);
});
y más del 300% con el más simple:
var strPath = ''/usr'';
var fm = $.NSFileManager.defaultManager,
lstFiles = ObjC.unwrap(
fm.contentsOfDirectoryAtPathError(strPath, null)
),
lstHarvest = [];
lstFiles.forEach(function (oItem) {
lstHarvest.push(
ObjC.unwrap(oItem)
);
});
Puedo obtenerlo así
foldersList = foldersList = System.folders.byName("usr").folders.name()
-> ["bin", "lib", "libexec", "sbin", "compartir", "independiente", "X11"]
E incluso esto funciona:
foldersList = System.folders.byName("/Users/USERName/Documents/").folders.name()
Pero hasta ahora no puedo hacer que el comando Ruta trabaje en nada más que ''abrir''