I would like to know if there is a command that returns the executable within the application bundle
Non esiste un comando di questo tipo, ma ho scritto uno script di shell che esegue esattamente per qualsiasi pacchetto di applicazioni nel file system del disco di avvio .
Utilizza diversi strumenti da riga di comando inclusi in macOS e sfrutta la documentazione di Apple su Avvia servizi , Pacchetti di applicazioni e Core Foundation Keys . Lo script fa quanto segue:
- Cerca
/Applications
per il pacchetto di applicazioni.
- Se non può essere trovato in
/Applications
, esegue una query sul database di Launch Services, considerando solo i pacchetti di applicazioni sul disco di avvio.
- Se è stato trovato un pacchetto di applicazioni, ispeziona
Info.plist
del pacchetto e cerca una chiave denominata CFBundleExecutable
che memorizza l'eseguibile (vedi sotto nella sezione delle informazioni di background per ulteriori informazioni su questo). Altrimenti, stampa un messaggio di errore e uscita.
- Stampa il percorso dell'eseguibile sullo standard output.
Lo script comprende sia il nome di un'applicazione con o senza la sua estensione, controlla gli argomenti, visualizza un messaggio di utilizzo e una breve descrizione se eseguito senza argomenti e restituisce uno stato di uscita con un messaggio di errore se necessario.
Poiché lo script ricerca /Applications
e potrebbe richiedere una query dispendiosa in termini di tempo per avviare i servizi, non è velocissimo (da ~ 1 secondo a diversi secondi), ma era accurato al 100% nei miei test .
Questo è lo script, con spiegazioni su ciò che viene fatto in ogni passaggio:
#!/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
Puoi salvare il file (ad esempio pbex
per "eseguibile bundle di stampa") e renderlo eseguibile come segue:
chmod a+x pbex
Se preferisci una funzione, usa invece:
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
}
Basta aggiungerlo a .bashrc
, sorgente:
. .bashrc
per utilizzare la funzione.
Se devi eseguirlo come (piuttosto lungo) "one-liner", usa (sostituisci <app name>
con il nome dell'applicazione senza l'estensione .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"
(Scrivi in un commento che il "comando deve essere lanciato da un QProcess"). Potresti fare quanto segue:
process.start("bash", QStringList() << "-c" << "app_name=\"<app name>\.app"; ...");
Vedi link per ulteriori informazioni.)
Esempi:
$ 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
INFORMAZIONI DI BASE
La struttura di un pacchetto di app per bundle macOS è ben nota e documentata da Apple.
Secondo La struttura di un pacchetto di applicazioni macOS , la struttura di base di un'app per Mac è:
MyApp.app/
Contents/
Info.plist
MacOS/
Resources/
dove la cartella MacOS
" contiene il codice eseguibile autonomo dell'applicazione . In genere, questa directory contiene solo un file binario con il punto di ingresso principale dell'applicazione e il codice collegato in modo statico Tuttavia, in questa directory è possibile inserire anche altri eseguibili standalone (come strumenti da riga di comando). "
Il file Info.plist
è necessario affinché il Finder riconosca un pacchetto di applicazioni come tale. Questa lista di proprietà di informazioni filecontains i dati di elenco di proprietà XML che identifica la configurazione del pacchetto. La chiave che ci interessa è CFBundleExecutable
, che memorizza " il nome del file eseguibile principale . Questo è il codice che viene eseguito quando l'utente lancia il tuo applicazione ".