Cómo obtener una ruta ejecutable de la aplicación desde la Terminal

4

En macOS, las aplicaciones se pueden iniciar desde la línea de comandos con open -a < application name> .

Me gustaría saber si hay un comando que devuelve el ejecutable dentro de el paquete de la aplicación, cuando la aplicación no se está ejecutando, espero algo como esto:

awesomeCommand <application name>
/Applications/***/MacOS/Content/application_executable
    
pregunta Mathieu Westphal 24.08.2018 - 16:15

2 respuestas

8
  

Me gustaría saber si hay un comando que devuelve el ejecutable dentro del paquete de aplicaciones

No hay tal comando, pero he escrito un script de shell que hace exactamente eso para cualquier paquete de aplicaciones en el sistema de archivos de su disco de inicio .

Utiliza varias herramientas de línea de comandos incluidas en macOS y aprovecha la documentación de Apple en Launch Services , Application Bundles y Core Foundation Keys . El script hace lo siguiente:

  1. Busca /Applications para el paquete de aplicaciones.
  2. Si no se puede encontrar en /Applications , consulta la base de datos de Servicios de lanzamiento, solo considerando paquetes de aplicaciones en el disco de inicio.
  3. Si se encontró un paquete de aplicaciones, inspecciona el Info.plist del paquete y busca una clave llamada CFBundleExecutable que almacene el archivo ejecutable (consulte más abajo en la sección de información de fondo). De lo contrario, imprima un mensaje de error y una salida.
  4. Imprime la ruta del ejecutable a la salida estándar.

El script entiende tanto el nombre de una aplicación con o sin su extensión, verifica los argumentos, muestra un mensaje de uso y una breve descripción si se ejecuta sin argumentos y devuelve un estado de salida con un mensaje de error si es necesario.

Como la secuencia de comandos busca /Applications y puede hacer una consulta lenta a los Servicios de inicio, no es muy rápida (de ~ 1 seg a varios segundos), pero fue 100% precisa en mis pruebas .

Este es el script, con explicaciones sobre lo que se hace en cada paso:

#!/bin/bash

# https://apple.stackexchange.com/a/334635
# Variables    
app_name="";
app_path_and_name="";
path_to_lsregister="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/";

# If run without arguments, issue a usage summary and exit
if [[ "$1" == "" ]]; then
    echo "$(basename $0): returns name of bundle applications’s executable file";
    echo "usage: $(basename $0) [application name]"; 
    exit 0;
fi;

# If argument doesn't end with '.app', append it
if [[ "$1" =~ \.app$ ]]; then
    app_name="$1"
else
    app_name="$1.app";
fi;

# Look for the path of the application bundle
# Search /Applicatinos first
app_path_and_name="$(find /Applications -type d -name "$app_name" -maxdepth 5 | grep -m 1 "$app_name")";
# If not found, search the the LaunchServices database (this is the time-consuming task)
test "$app_path_and_name" || app_path_and_name="$($path_to_lsregister/lsregister -dump | grep -v /Volumes | egrep --max-count 1 "/$app_name$" | sed 's:.* \(/.*\)::')"
# Check if Info.plist exists and is readable
if [[ -r "$app_path_and_name/Contents/Info.plist" ]]; then
    # Extract the CFBundleExecutable key that contains the name of the executable and print it to standard output
    echo "$app_path_and_name/MacOS/$(defaults read "$app_path_and_name/Contents/Info.plist" CFBundleExecutable)";
    exit 0;
else
    echo "Application '$1' not found";
    exit 1
fi

Puede guardar el archivo (por ejemplo, como pbex para "imprimir paquete ejecutable") y hacerlo ejecutable de la siguiente manera:

chmod a+x pbex

Si prefieres una función, usa esto en su lugar:

function pbex ()
{ 
    # https://apple.stackexchange.com/a/334635
    # Variables
    local app_name="";
    local app_path_and_name="";
    local path_to_lsregister="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/";

    # If run without arguments, issue a usage summary and exit
    if [[ "$1" == "" ]]; then
        echo "$FUNCNAME: returns name of bundle applications’s executable file";
        echo "usage: $FUNCNAME [application name]"; 
        return 0;
    fi;

    # If argument doesn't end with '.app', append it
    if [[ "$1" =~ \.app$ ]]; then
        app_name="$1"
    else
        app_name="$1.app";
    fi;

    # Look for the path of the application bundle
    # Search /Applicatinos first
    app_path_and_name="$(find /Applications -type d -name "$app_name" -maxdepth 5 | grep -m 1 "$app_name")";
    # If not found, search the LaunchServices database (this is the time-consuming step)
    test "$app_path_and_name" || app_path_and_name="$($path_to_lsregister/lsregister -dump | grep -v /Volumes | egrep --max-count 1 "/$app_name$" | sed 's:.* \(/.*\)::')"
    # Check if Info.plist exists and is readable
    if [[ -r "$app_path_and_name/Contents/Info.plist" ]]; then
        # Extract the CFBundleExecutable key that contains the name of the executable and print it to standard output
        echo "$app_path_and_name/MacOS/$(defaults read "$app_path_and_name/Contents/Info.plist" CFBundleExecutable)";
        return 0;
    else
        echo "Application '$1' not found";
        return 1
    fi
}

Solo agrégalo a .bashrc , fuente:

. .bashrc

para usar la función.

Si necesita ejecutarlo como "una sola línea" (bastante larga), use (reemplace <app name> con el nombre de la aplicación sin la extensión .app):

bash -c "app_name=\"<app name>\.app"; app_path_and_name=\"\"; if [[ \"\$app_name\" == \"\" ]]; then exit 2; fi; app_path_and_name=\"\$(find /Applications -type d -name \"\$app_name\" -maxdepth 5 | grep -m 1 \"\$app_name\")\"; test \"\$app_path_and_name\" || app_path_and_name=\"\$(/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump | grep -v /Volumes | egrep --max-count 1 \"/\$app_name\$\" | sed \"s:.* \(/.*\)::\")\"; if [[ -r \"\$app_path_and_name/Contents/Info.plist\" ]]; then echo \"\$app_path_and_name/MacOS/\$(defaults read \"\$app_path_and_name/Contents/Info.plist\" CFBundleExecutable)\"; exit 0; else echo \"Application \"\$app_name\" not found\"; exit 1; fi"

(Usted escribe en un comentario que el "comando debe iniciarse desde dentro de un QProcess"). Podrías hacer lo siguiente:

process.start("bash", QStringList() << "-c" << "app_name=\"<app name>\.app"; ...");

Consulte enlace para obtener más información.)

Ejemplos:

$ pbex
pbex: returns name of bundle applications’s executable file
usage: pbex [application name]
$ pbex "Microsoft Edge"
Application 'Microsoft Edge' not found
$ pbex Finder
/System/Library/CoreServices/Finder.app/MacOS/Finder
$ pbex "Quick Look Simulator.app"
/System/Library/Frameworks/Quartz.framework/Versions/A/Frameworks/QuickLookUI.framework/Versions/A/Resources/Quick Look Simulator.app/MacOS/Quick Look Simulator
$ pbex "BalTax 2016"
/Applications/BalTax 2016/BalTax 2016.app/MacOS/JavaApplicationStub
$ pbex ColorSync\ Utility
/Applications/Utilities/ColorSync Utility.app/MacOS/ColorSync Utility

INFORMACIÓN DE ANTECEDENTES

La estructura de un paquete de aplicaciones del paquete macOS es bien conocida y está documentada por Apple.

Según la estructura de un paquete de aplicaciones macOS , la estructura básica de una aplicación para Mac es:

MyApp.app/
   Contents/
      Info.plist
      MacOS/
      Resources/ 

donde la carpeta MacOS " contiene el código ejecutable independiente de la aplicación. Normalmente, este directorio contiene solo un archivo binario con el punto de entrada principal de la aplicación y el código vinculado estáticamente Sin embargo, también puede poner otros ejecutables independientes (como herramientas de línea de comandos) en este directorio ".

El archivo Info.plist es necesario para que el Finder reconozca un paquete de aplicaciones como tal. Esta lista de propiedades de información contiene archivos de lista de propiedades XML que identifican la configuración de su paquete. La clave que nos interesa es CFBundleExecutable , que almacena " el nombre del archivo ejecutable principal . Este es el código que se ejecuta cuando el usuario inicia su cuenta. aplicación. "

    
respondido por el jaume 24.08.2018 - 19:02
2

No es exactamente un solo comando, pero puedo darte los pasos para obtener la información. Esta información proviene de Guía de programación de paquetes .

Debe conocer la estructura de una aplicación.

En su directorio raíz se encuentra un contenido del directorio. En ese directorio hay un directorio MacOS que contiene el código ejecutable independiente de la aplicación y un archivo Info.plist

Info.plist es un archivo con formato plist que contiene información sobre la aplicación, incluido el nombre del archivo ejecutable principal. Este nombre es el valor correspondiente a la clave CFBundleExecutable.

Por lo tanto, el algoritmo para encontrar las aplicaciones que inician el ejecutable es

  1. Encuentra la aplicación
  2. Encuentre el directorio de contenidos de la aplicación
  3. Lea el archivo Info.plist que obtiene el valor de CFBundleExecutable
  4. el ejecutable está en el directorio de MacOs de 2 y se llama el resultado de 3.

Tenga en cuenta que los pasos 1 y 3 no son triviales y requieren llamadas a las bibliotecas del sistema de Apple

    
respondido por el Mark 24.08.2018 - 18:26

Lea otras preguntas en las etiquetas