0

Similar to "How to find Bundle Identifier from known PID?" and to "How to read plist information (bundle id) from a shell script, but different.. as those are both related to Xcode build variable expansion, etc.

My question is how, in a BASH shell, where they only known value is the process' PID, how can one obtain that process' PATH, or unique "Bundle ID".

I am sure there is a hideous regex to parse ps, but I'm hoping for something cleaner and more portable. The comments in those prior mentioned posts included

BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "${BUILD_ROOT}/${INFOPLIST_PATH}")

However, I do not think plistbuddy is installed on every Mac, and more importantly, my question is within a theoretical script, NOT within an Xcode build phase..

I've tried plutil, plistkit, and plistdump, and none of them seem to do the trick..

The reason I am trying to achieve this is to be able to execute defaults read / write functions without hardcoding the BundleID of the parent process. I know how to pass this info as an argument to a script.. but I want to be able to doubt check.. within the script.

Community
  • 1
  • 1
Alex Gray
  • 16,007
  • 9
  • 96
  • 118
  • i accept them when they're answered. also, I've answered 70 questions vs. asking 16. and most of them already had accepted answers. i post when i can add to the solution.. and i accept an answer when it solves the problem, not just because someone posted it. – Alex Gray Jan 13 '12 at 07:20

1 Answers1

2

No need for a hideous regex to parse the output of ps – the ps utility already does what you ask of it. Calling it with the (admittedly somewhat arcane looking) following options

ps [-ww] -o comm= -p <pid>

will return the path to the executable belonging to your PID (the -ww argument is only needed if you output to a terminal, as ps will truncate the returned path without it. It should not be necessary otherwise).

The problem with retrieving a bundle ID from there is that not all processes map to bundles with an Info.plist (which defines the bundle ID) – notably, *nix type executables are not bundles and thus have no bundle ID. Also, even in the case of app bundles, ps returns the core executable of an application, not the path to the bundle itself. As the path to the executable inside an application bundle is standardized, however (it resides in Path.app/Contents/MacOS), you can retrieve it with a bit of directory traversal.

Assuming you have stored the output of the ps call above in the variable execfile, this

[[ ${execfile%/*} =~ ^.+/Contents/MacOS$ ]] && defaults read "${execfile%/*/*}"/Info CFBundleIdentifier

will retrieve bundle identifiers for likely paths by using defaults to retrieve the value of the CFBundleIdentifier key of the Info.plist file every application bundle contains at its root.

kopischke
  • 3,393
  • 1
  • 21
  • 40
  • Anything that remains arcane in 2012 is usually also known as "discouraged". I don't think "they" want "us" to do this. Looks good though... will test and report back. – Alex Gray May 02 '12 at 18:22
  • 1
    @alexgray: I tend to agree on the first part (two decades of evolution of the \*nix toolchain do not stop me from muttering passages straight out of the *Unix Haters Handbook* whenever I delve into the shell… I mean: `-ww`? really?). Did work on my system, for what it is worth. – kopischke May 02 '12 at 18:30
  • Ha! I had never heard of [The Unix Hater's Handbook](http://m.simson.net/ugh.pdf). Hillarious. – Alex Gray May 02 '12 at 18:38
  • Fact I own a first hand, then new paperback copy serves as a good reminder I’ve been around computers far too long. So has the \*nix toolchain. Closing this off before some mod nukes the whole comment thread for being OT. Which it totally is. – kopischke May 02 '12 at 18:43
  • Works like a charm… `execfile=\`ps -ww -o comm= -p 48022\` && [[ ${execfile%/*} =~ ^.+/Contents/MacOS$ ]] && defaults read "${execfile%/*/*}"/Info CFBundleIdentifier` -> com.mrgray.whatever. Now I just have to remember why I wanted to do this, lol. PS: Hope your copy came with the [UNIX barf bag](http://en.wikipedia.org/wiki/The_UNIX-HATERS_Handbook)! – Alex Gray May 02 '12 at 18:45
  • @alexgray: well, “they” recommend “we” use `$()` instead of back ticks. Otherwise, glad it works for you. – kopischke May 02 '12 at 18:47
  • 2
    Just a note about why this works: `defaults read` is pulling a value from the application bundle's Info.plist file. Expanding the final part of @kopischke's command expanded looks like this: `defaults read /Applications/Mail.app/Contents/Info CFBundleIdentifier` which returns `com.apple.mail` – joemaller Jul 15 '13 at 02:34
  • @joemaller thanks for clarifying – as OP knew the internals, my solution was admittedly light on basic explanation. Amended. – kopischke Jul 15 '13 at 13:08