Tuesday, December 20, 2022

How to add graphical apps to shell $PATH in macOS

Apple macOS 13 does not add new installed .app programs to $PATH automatically (probably not a good idea), so if desired must be added manually.

First, create a local directory to put there the symbolic links:

How to a add a local directory to $PATH in macOS

To add symlinks you must first find where the main exec file that launches the program is located at. Examples programs with or without user interface:

ln -sn /Applications/kate.app/Contents/MacOS/kate "~/zshbin/kate"
ln -sn ~/Library/Android/sdk/platform-tools/adb "~/zshbin/adb"
ln -sn /Applications/Hex\ Fiend.app/Contents/MacOS/Hex\ Fiend "~/zshbin/hexfiend"

You can easily find where the main binary exec file is located at, for any given graphical app with this bash script:

#!/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 | fgrep -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 | fgrep -v '/Volumes|/System' | egrep --max-count 1 "path: */.*/$app_name " | sed 's:.* \(/.*app\) .*:\1:')"
#echo $app_path_and_name
# 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/Contents/MacOS/$(defaults read "$app_path_and_name/Contents/Info.plist" CFBundleExecutable)";
    exit 0;
# Check if it's an app for Apple mobile devices compatible with Apple Silicon desktops: iOS, iPadOS, possibly (not tested) watchOS and tvOS, so on
# https://apple.stackexchange.com/questions/452340/how-to-launch-ios-ipados-apps-from-shell-in-macos-with-apple-silicon
elif [[ -r "$app_path_and_name/WrappedBundle" ]] || [[ -r "$app_path_and_name/Wrapper" ]]; then
    echo -n "'"
    echo -n "$(basename "$app_path_and_name" .app)"
    echo -n "'"
    echo " is a mobile native app, launch with:";
    echo "open -a '$app_path_and_name'"
    exit 0;
else
    echo "Application '$1' not found";
    exit 1
fi
You can also do it with a bash function, etc.
Save it to "~/zshbin/" and "chmod +x ~/zshbin/appath"

If the app is running under macOS with compatibility mode for iOS/iPadOS and other mobile systems, I don't think you can't run the exec directly, since it's structured differently inside. You must run:
open -a '/Applications/the app.app'

Now run on desired app name:

appath 'Hex Fiend'
/Applications/Hex Fiend.app/MacOS/Contents/Hex Fiend

Then run the symlink as usual:

ln -sn "/Applications/Hex Fiend.app/Contents/MacOS/Hex Fiend" "~/zshbin/hexfiend"

or you can call directly the script to auto detect binary launcher and add the symlink to it:

ln -sn "$(appath 'Hex Fiend')" "~/zshbin/hexfiend"


You can get all main exec file for most standard installed .app applications automatically so you don't have the guess App names:

for i in /Applications/*.app ; do appath "$(basename $i .app)" ; done | sort | uniq

Basically you have to find the file "Info.plist" inside each .app folder, and read from that file the next line after "<key>CFBundleExecutable</key>".


Links

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.