Plistbuddy - How to catch errors (key does not exist)

I am reading a plist file using plistbuddy ; and I collect data from different dictionaries.

The problem is that sometimes values ​​do not exist for one reason or another, so I get the output "Key does not exist" .

Is there a way to intercept this, so if the value does not exist, can I replace it with 0 or another value?

I am using a shell script; I thought of using a simple if ... else , I tried to check the line "Key does not exist" , but it doesn’t work (I never got into the true condition, I assume that the message is just collected in stdout, and not stored in my variable )

The documentation didn't help, so I'm stuck.

Since I am calculating the average, the error will interfere with my calculation, and therefore I want to add 0, so I can check later if there is 0, and change the function to calculate the average accordingly.

This is basically an example of my code: (filename is the name of the plist file)

 for i in {0..3} do TempValue=$(/usr/libexec/PlistBuddy -c "print :process:$i:testname:result" $fileName) echo $TempValue Data_results+=($TempValue) done # Calculate Average tmpResult=`echo ${Data_results[0]} + ${Data_results[1]} + ${Data_results[2]} + ${Data_results[3]}|bc` AverageTime=$(bc <<< "scale=10; $tmpResult / 4") echo "average for test name: " $AverageValue 

Thanks!

+8
bash error-handling
source share
1 answer

The OS X /usr/libexec/PlistBuddy is a well-executed CLI:

  • if successful, its exit code is 0
  • in case of failure, its exit code is not equal to zero
  • its regular output is sent to stdout , error messages are sent to stderr

There are various ways to verify success; eg:.

 # Query and save the value; suppress any error message, if key not found. val=$(/usr/libexec/PlistBuddy -c 'print ":SomeKey"' file 2>/dev/null) # Save the exit code, which indicates success v. failure exitCode=$? if (( exitCode == 0 )) then # OK # handle success .... else # handle failure ... fi 

Update 1

Here is a snippet of your specific use case; you can run it as is to see how it works (it uses the Plist file in which the Finder saves its settings):

 # Loop over keys and retrieve the corresponding values. # If the key doesn't exist, assign '0'. for key in ':AppleShowAllFiles' ':NoSuchKey'; do val=$(/usr/libexec/PlistBuddy -c "print \"$key\"" \ ~/Library/Preferences/com.apple.finder.plist 2>/dev/null || printf '0') echo "Value retrieved: [$val]" done 

As you will see, $val will contain 0 in the case of a 2nd, nonexistent key.

2>/dev/null suppress stderr output (error messages) and operator || used to provide an alternative command to create output in the event that a call to PlistBuddy indicates a failure (via its exit code).

The only caveat is that you cannot distinguish a nonexistent key from a more fundamental failure, such as a nonexistent or damaged Plist file. Processing will be more attractive since PlistBuddy does not use different exit codes to distinguish between these cases.


Update 2

Here's a simplified version of your code that includes the desired default 0 logic:

 # Collect temperatures. Data_results=() for i in {0..3} do Data_results+=( $(/usr/libexec/PlistBuddy \ -c "print :process:$i:testname:result" "$fileName" 2>/dev/null || printf '0') ) done # Calculate average AverageValue=$(bc <<< \ "scale=10; $(( ${Data_results[@]/%/ +} 0 )) / ${#Data_results[@]}") echo "average for test name: " $AverageValue 

Note: $(( ... )) is an arithmetic extension (only integers) that uses a little trick to sum the elements of the array: ${Data_results[@]/%/ +} + to each element of the array. For example, the input array from (1 2 3) will expand to 1 + 2 + 3 + ; since this leaves a dangling + , I just added another 0 to form the correct expression. In combination with dividing by ${#Data_results[@]} - the number of elements in the array - the command then works with an array of any size.

+10
source share

All Articles