Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

mikezang

macrumors 6502a
Original poster
May 22, 2010
938
41
Tokyo, Japan
I have a plist file as below
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
* <dict>
* * <key>showName</key>
* * <string>Name1</string>
* * <key>videoURLString</key>
* * <string>http://ip1/file1.txt</string>
* </dict>
* <dict>
* * <key>showName</key>
* * <string>Name2</string>
* * <key>videoURLString</key>
* * <string>http://ip2/file2.txt</string>
* </dict>
</array>
</plist>
I want to get showName and videoYRLString then run
"curl $videURLString -o $showName"
to download files, but I am not sure hot to do, pls help me.
Code:
plistfile="${HOME}/Downloads.plist"

showName="$(/usr/libexec/PlistBuddy -c "Print" "${plistfile}" | awk '/showName = /{print $3}' | awk -F' ' '{print $1}')"
videoURLString="$(/usr/libexec/PlistBuddy -c "Print" "${plistfile}" | awk '/videoURLString = /{print $3}' )"


printf "%s\n" "${showName[@]}"
printf "%s\n" "${videoURLString[@]}"*
 
There are several possible ways to perform curl on all the things that were found.

One of the simplest is to do it all in 'awk'. Write a single awk program that has the following pattern-matches:
  • for the pattern /showName = /, append $3 to an array of names.
  • for the pattern /videoURLString = /, append $3 to an array of URLs.
  • for the special pattern END (see awk's man page), loop thru the names and URLs, performing the desired curl command using the system command.
In short, use awk to perform all the matching, collecting, iterating, and curl'ing. Right now, you're only using awk as a variation of grep. It's much more powerful than that. Study the awk man page, and maybe look at a tutorial on awk that covers the BEGIN and END patterns.

An alternative is to use a shell 'for' command to iterate over the arrays, and run curl on each indexed name and url. You might also use the 'xargs' command. Personally, I think both alternatives are more complex than simply using awk.
 
There are several possible ways to perform curl on all the things that were found.

One of the simplest is to do it all in 'awk'. Write a single awk program that has the following pattern-matches:
  • for the pattern /showName = /, append $3 to an array of names.
  • for the pattern /videoURLString = /, append $3 to an array of URLs.
  • for the special pattern END (see awk's man page), loop thru the names and URLs, performing the desired curl command using the system command.
In short, use awk to perform all the matching, collecting, iterating, and curl'ing. Right now, you're only using awk as a variation of grep. It's much more powerful than that. Study the awk man page, and maybe look at a tutorial on awk that covers the BEGIN and END patterns.

An alternative is to use a shell 'for' command to iterate over the arrays, and run curl on each indexed name and url. You might also use the 'xargs' command. Personally, I think both alternatives are more complex than simply using awk.
Thanks for yor reply. I am reading guide, for example, sed & awk, and so on.
As you you know, it is not easy even if you read a lot of guide of programming, it need time, but I want to use it soon.
Can you show me code to do what I need by awk?
 
This is an example as I described:

File: example.awk
Code:
# array indexes zeroed
BEGIN { n = 0; u = 0;  }

# match patterns from PlistBuddy output
/showName = /  { names[ n++ ] = $3; }
/videoURLString = /  { urls[ u++ ] = $3; }

# when no more input, process everything
END {
  if ( n != u )  { print "Unequal counts, n: " n ", u: " u;  exit 1; }

  for ( i = 0; i < n; ++i ) {
    print "name", names[ i ], "url", urls[ i ];
    # build cmd-string and put system() here
  }
}
Command-line:
Code:
PlistBuddy -c print array.plist | awk -f example.awk


This is a simpler one that runs curl incrementally.

File: curly.awk
Code:
# keep name for later
/showName = /  { name = $3 }

# process name and url
/videoURLString = /  {
  cmd = "curl " $3 " -o " name
  print "cmd:", cmd

  ## disabled for testing (inspect output for correctness)
#  status = system( cmd )
#  if ( status != 0 )  { print "curl failed:", status; exit status }
}

Command-line:
Code:
PlistBuddy -c print array.plist | awk -f curly.awk


None of these account for the possibility of spaces in the name, quotes or other special characters in the name or URL, and probably various other shortcomings. This is why it's important to run tests first, and confirm the output looks correct WITHOUT running the curl command.

You could also break it down into two parts. The first awk script simply produces the correct output, with the name first and the url second on each line. The second awk script then reads that list, and runs curl on $1 and $2. This is left as an exercise for the reader.
 
This is an example as I described:

<SNIP>
Thanks for your samples! The first is good, but second seems has a bug, because I will get results as below, Name is shift..
Code:
cmd: curl http://ip1/file1.txt -o 
cmd: curl http://ip1/file1.txt -o Name1
 
Last edited by a moderator:
Post your real data.

In particular, run the PlistBuddy command and redirect its output to a file. Look at that file very carefully, for reasons why it might produce the output shown, then post that file.

Also post the actual plist that produces this output.


The only data you've posted is in your initial post. And it's not even a real plist, because it contains *'s that must be removed. You need to show real data.
 
Last edited:
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.