1

I've looked into using PlistBuddy and plutil but most examples such as:

How do I replace a value in an plist array using plutil?

seem to suggest setting the value of a key, which is not the case here.

I want to modify a value I do not know exists or not. See, I don't know what the key is. I want to automate it.

So if you can search for a value, get the value and key then I could possibly use the above to set a new value on the key.

But i have not figured out a way to do that.

Do you know? Preferably in Bash.

10
  • Can you provide a sample of the property list data you'll be working with and highlight where the value of interest sits ?
    – CJK
    Nov 7 '19 at 12:36
  • @CJK No, I can not. The value could be in 10-30 files and I can not make any assumptions and generally I would refuse to make solutions around a particular use case, or understood use case. Either way, I've already solved it. I will be posting the answer later here.
    – mmm
    Nov 7 '19 at 13:25
  • Well done for solving it. For future reference, sample data isn't requested to tailor a solution specifically to a single use case. It's asked for one or more of these reasons:
    – CJK
    Nov 7 '19 at 15:23
  • to better illustrate the nature of the question and reduce back-and-forth for clarification; to give an example use case that provides a starting point for testing purposes; to help reduce workload by sparing the need for the programmer to "invent" their first data set, and the pain of typing out what could be pasted; to give a common dataset all users can use to correlate their solution against others early; to propose a different approach to the problem that might be simpler/faster/more generalised by first mutating the data in a specific way; other reasons, probably worthy albeit opaque
    – CJK
    Nov 7 '19 at 15:27
  • abc.plist ... contains: aaa bbb ccc ddd aaa bbb ccc; Now I wish to replace the value aaa with whatever i desire.
    – mmm
    Nov 7 '19 at 16:11
0
######################################## BASH LIB #######################################
bash.string.replace() {
        local text="$1" find="$2" replace="$3";

        echo "${text}" | while IFS= read -r line; do 
                printf '%s\n' "${line//"$find"/$replace}"; 
        done 
}
######################################## BASH LIB #######################################

######################################## APPLE LIB ######################################
apple.plist.read() {
        local filepath="${1}"

        defaults read "${filepath}"                
}
apple.plist.convert.to.xml() {
        local filepath="${1}" tmp="${2}"

        # If second argument is passed, then we save the conversion to a new file rather than write over the original
        if [[ "${tmp}" == "true" ]]; then
            tmp="/tmp${filepath}"
        fi 

        if [[ "${tmp}" != "" ]]; then
            bash.cp "${filepath}" "${tmp}"

            filepath="${tmp}"
        fi

        plutil -convert xml1 "${filepath}"

        # We also output the content which can be supressed if desired by caller
        cat "${filepath}"                
}
apple.plist.convert.to.binary() {
        local filepath="${1}"

        plutil -convert binary1 "${filepath}"                
}
apple.plist.write() {
        local filepath="$1" text="$2"

        echo "${text}" > "${filepath}"

        apple.plist.convert.to.binary "${filepath}" # Not sure if this step is neccessary, if xml representation is enough. Not verified or tested without. 
}
apple.plist.read.search.replace.write() {
        local file="${1}" search="${2}" replacement="${3}"

        local updated=$(bash.string.replace "$(apple.plist.read "${file}")" "${search}" "${replacement}")

        apple.plist.write "${file}" "${updated}"
}
######################################## APPLE LIB ######################################


######################################## EXAMPLE ##################################
my.test.1() {
    apple.plist.read.search.replace.write "/tmp/com.apple.finder.plist" "/Users/" "/Home/"
}
######################################## EXAMPLE ##################################

Basically we call the function plist.read.search.replace.write with file arguments and what to replace which will read it to text, then we perform a replacement on that text, and then write that text back using plist.write which will also convert it from xml (which it will be) to binary using plutil -convert xml1 "/path/to/file".

Rather than read using defaults read "..." we could in theory instad use plutil convert to xml but likely more expensive.

8
  • Now I have more logic concerning to apple.plist, like search a bunch of files and replace but this was the answer to the question.
    – mmm
    Nov 9 '19 at 22:39
  • 1
    I like your coding style. It's very logical and clear.
    – CJK
    Nov 10 '19 at 20:36
  • Thank you, I've peeked on yours too. I like it! I wan't to figure out more about AppleScript and it's limitations. Is it possible to code AppleScript similar logic in JavaScript? I know you can execute js, but not sure how limited it is. Like control windows and what not. Other option I guess is Swift. AppleScript is nice for small things, but kind of difficult to do complex stuff. I've done some mostly through Keyboard Maestro but it can get pretty complex and difficult to maintain quickly. Also been considering hammerspoon, but why lua if JS possible?
    – mmm
    Nov 11 '19 at 0:39
  • 1
    AppleScript does have its limitations, but was only ever designed with a very specific remit. Are you familiar with JavaScript for Automation aka "JXA" ? In case you hadn't heard of it, it's the JavaScript version of AppleScript, so will undoubtedly feel a lot easier to code in if you're already familiar with JS. Hammerspoon is underrated and lacks the fame of AppleScript (some well-known developers don't even know it exists). But it is impressive, uses low-level C APIs, and Lua is easy to learn. But, yes, Swift (and now SwiftUI) would be good to look into for software development.
    – CJK
    Nov 11 '19 at 1:27
  • @CJK Thank you! Do you think hammerspoon & lua would be more powerful / more feature rich than JXA? The only problem I have if one where to be able to develop something releasable, is how to bundle it. You'd have to require hammerspoon to be installed, or if possible bundle it in I guess. Lua is also another language to learn. Would you say everything is possible to do with Swift / Swift UI so maybe Hammerspoon would be a stray way?
    – mmm
    Nov 12 '19 at 14:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .