0 votos

si disco externo encontrado por terminal applescript

Los MacBooks tienen la mala costumbre de no montar los discos externos cuando se conectan antes de... enlace de referencia

la solución es bastante simple con el terminal de expulsar el disco y el manualmente desenchufe vuelva a conectar la unidad.

Me gustaría hacer un pequeño AppleScript que pueda hacer todo el proceso de buscar el disco y si lo encuentra expulsarlo. Esto es lo que tengo, pero estoy atascado en reconocer si el disco externo es encontrado por el terminal...

tell application "Terminal"
do script "echo \"diskutil list\"" in window 1
if exists disk2 then
    do script "echo \"diskutil info disk2\"" in window 1
    do script "echo \"diskutil eject disk2\"" in window 1
    do script "echo \"diskutil list\"" in window 1
end if
end tell

el error que obtengo es La variable disk2 no está definida. Las preguntas son: 1) si imprimo la lista de diskutil, ¿cómo definiría variables para todos los terminales de disco externos encontrados? 2) ¿ver si está montado, si no intentar montar, si falla expulsar?

0 votos

Yo intentaría montar todo lo que encuentre. Echa un vistazo a los bloques "Try...End Try". Tienen la ventaja de fallar silenciosamente. Esto puede ahorrarte un MONTÓN de "if exists..." y otros códigos repetitivos. Ten en cuenta que es mejor poner tus sentencias try-end try en después de consigues que funcione el algoritmo básico los pongo, luego --comento después de probar cada parte del script. Es agradable no obtener un diálogo script de Apple, cuando estás tratando de leer un libro.

0 votos

Yo, por principio, haría caso omiso de los consejos que da @WayfaringStranger aquí. En general no cómo utilizar ni por qué se implementaría la captura de errores, y un montón de "repetitivos". if exists... "La codificación puede ser laboriosa, sin duda, pero es absolutamente la forma correcta de hacer las cosas. Pero, como @Rottjung es un programador de C++, sospecho que ya lo sabe, así que este comentario va dirigido a otros lectores en general que no quieran adquirir malos hábitos en el scripting.

0 votos

@CJK Espere a llegar a cinco páginas en su "si existe". Al igual que la antigua controversia "go to", los bloques Try-End try pueden deshacerse de montones masivos de código feo, y darte un producto mucho más legible y mantenible.

1voto

qarma Puntos 71

En realidad estás escribiendo un shell script, y el contexto AppleScript parece bastante superfluo por el momento. Si estás usando predominantemente comandos de shell, quizás quieras considerar escribir un script de shell en su lugar.

He empleado un poco de ambos porque cada uno tiene su utilidad en esta situación: los comandos de shell son necesarios para recuperar la información del disco a través de diskutil ya que AppleScript no tiene ningún medio incorporado para obtener esa información por sí mismo; pero entonces, en lugar de perder el tiempo con grep , awk o sed para que coincida con el patrón de texto de la salida sin procesar, podemos invocar la función -plist para devolver la salida como datos de lista de propiedades con formato XML, que AppleScript puede manejar muy bien.

1. Recuperación de una lista de discos y volúmenes locales

Los discos y volúmenes conectados localmente tienen un inodo blockdevice en la carpeta /dev por lo que obtener una lista de discos es bastante fácil con AppleScript:

use application "System Events"

property devices : a reference to files in folder "/dev"
property disknodes : a reference to (devices whose name begins with "disk")

set diskinfo to name of disknodes

Con mi unidad USB conectada, obtengo esta lista de inodos:

    --> {"disk0", "disk0s1", "disk0s2", "disk1", "disk1s1", 
         "disk1s2", "disk1s3", "disk1s4", "disk2", "disk2s1"}

2. Aislar los volúmenes deseados

Para filtrar la lista de forma que sólo ejecutemos las utilidades adecuadas en los discos o volúmenes adecuados, diskutil hace ahora su parte. Podemos crear un proceso shell desde dentro de AppleScript en lugar de hacerlo a través de Terminal . El comando de shell correspondiente es el siguiente:

diskutil info -plist <disk|volume>

Para ejecutar esto desde AppleScript, utilice la función do shell script mando:

do shell script "diskutil info -plist" & id

donde id es el nombre de un disco recuperado anteriormente y almacenado en diskinfo . No puedes pasar toda la lista de una vez, así que tenemos que iterar a través de la lista y ejecutar el comando una vez para cada elemento:

use scripting additions

delete every property list item
repeat with id in diskinfo
    set shellcmd to "diskutil info -plist " & id
    set plist to do shell script shellcmd

Con los datos de la lista de propiedades devueltos por diskutil AppleScript puede convertirlo en un property list objeto. Los datos de la lista de propiedades devueltos al invocar diskutil info está todo contenido en un único nivel, por lo que no hay que atravesar ninguna jerarquía. Lo mejor de property list objetos es que AppleScript puede transformarlos en un record lo que facilita enormemente la recuperación de valores:

    make property list item with properties {name:id, text:plist}
    tell the value of property list item id as record to if ¬
        (its |Ejectable|) and (not its WholeDisk) and ¬
        (its MountPoint = "") then set the contents of id ¬
        to its {disk:ParentWholeDisk, volume:DeviceIdentifier}
end repeat

En una sola línea, AppleScript ha leído los datos de la lista de propiedades y ha descartado cualquier disco que esté:

  1. No eyectable;
  2. Es un disco "entero" (es decir, no un volumen montable);
  3. Tiene un punto de montaje identificable en el sistema.

También elimina todos los datos inútiles que no necesitamos y sólo devuelve el nombre de la partición y su disco principal. Éstos sólo serán eyectable (es decir, no los discos de recuperación y arranque, ni el disco duro de su ordenador), y serán volúmenes montables que no están montados actualmente. Para mí, y mi única unidad USB, que desmonté primero, me devolvió esta lista de discos:

set unmounted to records of diskinfo
    --> {{disk:"disk2", volume:"disk2s1"}}

3. Montaje y expulsión de cada volumen

El análisis de los datos ya está hecho, así que ahora puede ejecutar diskutil en los discos correspondientes. Puede elegir entre montar volúmenes individuales o montar un disco entero (que montará todos sus volúmenes). El método es el mismo para cada uno: iterar a través de nuestra lista de registros almacenada en la variable unmounted y utilice disk o el volume de cada elemento como argumento para el comando shell apropiado:

diskutil mount <volume>
diskutil mountDisk <disk>
diskutil eject <disk>

El bucle AppleScript tiene el siguiente aspecto:

repeat with diskitem in unmounted
    set shellcmd to "diskutil mount " & diskitem's volume
    try
        do shell script shellcmd
    on error
        set shellcmd to "diskutil eject " & diskitem's disk
        try
            do shell script shellcmd
        end try
    end try
end repeat

do shell script devuelve en caso de éxito la salida a stdout . Después de montar con éxito mi disco, el panel de mensajes en script Editor contenido:

"Volume USB on disk2s1 mounted"

No he provocado una situación que obligue a mi unidad a no montarse, pero normalmente, al fallar cualquier comando de shell (es decir, siempre que un comando de shell devuelva un estado distinto de cero), do shell script arroja un error. Esto será detectado por el try que redirigirá el script para ejecutar otro comando de shell responsable de expulsar la unidad. Esto también está en su propio try por si también devuelve un estado distinto de cero, en cuyo caso el script continuará con el siguiente volumen.

A continuación se muestra el script final con algunas modificaciones adicionales. El script devolverá la lista original de registros desmontados con información extra añadida a cada elemento del disco informando del resultado del intento de montar y/o expulsar el volumen. Un fallo completo será simplemente reportado con false . Así que mi resultado final script se parecía a esto:

--> {{disk:"disk2", volume:"disk2s1", result:"Volume USB on disk2s1 mounted"}}

El script final

use application "System Events"

property devices : a reference to files in folder "/dev"
property disknodes : a reference to (devices whose name begins with "disk")

set diskinfo to name of disknodes

use scripting additions

delete every property list item
repeat with id in diskinfo
    set shellcmd to "diskutil info -plist " & id
    set plist to do shell script shellcmd
    make property list item with properties {name:id, text:plist}
    tell the value of property list item id as record ¬
        to if (its |Ejectable|) ¬
        and (not its WholeDisk) ¬
        and (its MountPoint = "") then set ¬
        id's contents to {disk:its ParentWholeDisk ¬
        , volume:its DeviceIdentifier ¬
        , result:missing value}
end repeat

set unmounted to records of diskinfo

repeat with diskitem in unmounted
    set shellcmd to "diskutil mount " & diskitem's volume
    try
        do shell script shellcmd
        set diskitem's result to the result
    on error
        set shellcmd to "diskutil eject " & diskitem's disk
        try
            do shell script shellcmd
            set diskitem's result to the result
        on error E
            set disk item's result to E
        end try
    end try
end repeat

return unmounted

0 votos

Tengo una pregunta sobre delete every property list item ... ¿De qué lista de propiedades se están eliminando los elementos y por qué es necesario?

0 votos

Se borra de Eventos del sistema que posee el property list item objetos en el nivel superior. Al crear un objeto huérfano property list item que no se ha leído de un property list file , Eventos del sistema los almacena en un contenedor temporal, aunque no sé dónde (probablemente un archivo temporal en un directorio temporal). Normalmente expiran tras unos 5 minutos de inactividad continua (es decir, AppleScript no ha accedido a sus datos en ese tiempo). Entre ejecuciones sucesivas de un script, se acumulan, lo que me irrita. Cont...

0 votos

...Con'td Pero lo más importante es que los datos no parecen sobrescribirse de forma consistente y fiable con nuevos datos en cada ejecución sucesiva del script, posiblemente porque declaré mis huérfanos con un específico name (aunque Eventos del sistema asigna a cada instancia su propio id ). Borrar todas las listas de propiedades al principio parece asegurar que los datos que estoy manejando son la versión más actualizada de los datos.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X