The Apple Geek

Чему ты научился сегодня?

Получение информации по приложениям iPhone в iTunes из shell

Как вы могли прочитать, у меня есть две учётные записи iTunes. Первая - традиционная в iTunes USA, которой я пользуюсь давно, покупая коды iTunes Gift Card. Вторая - новая в iTunes Russia, приложения я покупаю по привязанной карте Visa Classic.

Само собой с iTunes Russia всё просто - купил программу, небольшие деньги снялись с карты и всё. В iTunes USA нужны коды, я периодически их покупаю на $50 - $100, что пробивает дыру в бюджете. Но в USA Store есть и музыка, и фильмы, и все приложения. А вот в Russia Store часть программ попросту отсутствует, часть появляется с задержкой, а про музыку я вообще молчу - её нет.

Приходится пользоваться параллельно двумя учётными записями. Это вызывает неудобства с обновлениями - нужно явно перелогиниваться в нужный App Store. Поэтому я стараюсь удалить бесплатные программы из USA Store и установить их из Russia Store.

Когда программ от нескольких единиц до нескольких десятков, то это не вызывает сложностей. Но у меня их 252, причём явно ненужные мне программы я удаляю.

Вручную нажать 252 раз Cmd+I для просмотра, к какой учётной записи какая программа привязана, а потом ещё перейти в App Store, чтобы убедиться, какая из них бесплатная, это уже большой кусок работы.

Есть простая программа App Store Expense Monitor, показывающая затраты на все приложения, но мне она не подходит.

Поэтому я решил слегка автоматизировать процесс, составив список бесплатных программ, привязанных к старой учётной записи. Бесплатность придётся в любом случае перепроверять в iTunes App Store, но сделать это пару десятков раз проще, чем пару сотен раз.

Идея проста - в архиве приложения app.ipa (это zip-архив) в файле iTunesMetadata.plist находится вся нужная информация, включая имя учётной записи, дату покупки, стоимость и ещё много параметров. Приложения обычно находятся в каталоге “/Users/$USER/Music/iTunes/iTunes Music/Mobile Applications” (я не претендую на общий случай, в моём случае и 98% других случаях это так).

Например, вот так можно посмотреть информацию по программе Things (plist в программах может быть и в бинарном виде, поэтому нужно провести конвертацию в формат xml1 программой plutil):

$ unzip -p "/Users/$USER/Music/iTunes/iTunes Music/Mobile Applications/Things.ipa" \
    iTunesMetadata.plist | \
    plutil -convert xml1 - -o -

А дальше - наворачивание кода вокруг этой одной команды, чтобы привести вывод к виду, который мне нужен. Не претендую на оптимальность и универсальность кода, но он в моём случае работает.

Предупреждение. Ошибка в shell можно привести к разным результатам. Поэтому перез запуском чужих программ, скриптов и прочего убедитесь, что вы понимаете их назначение и имейте наготове резервную копию всех данных (клон, Time Machine, etc) - это никогда не будет лишним.

Вот моя программа, она также доступна в Dropbox:

#!/bin/sh
APPDIR="/Users/$USER/Music/iTunes/iTunes Music/Mobile Applications"
find "${APPDIR}" -name \*.ipa |
while read line
do
    unzip -p "${line}" iTunesMetadata.plist | plutil -convert xml1 - -o - | \
    grep -A 1 -i    -e "AppleID" -e "price" \
                    -e "priceDisplay" -e "itemName" \
                    -e "purchaseDate" | \
    grep -e string -e integer -e date | \
    sed -e 's/^.*<[a-z]*>//' -e 's/<\/[a-z]*>//' | \
    sed 's/T[0-9]*:[0-9]*:[0-9]*Z//' | \
    tr '\n' '\t' | \
    awk -F '\t' '{
        if ($5 ~ /20[0-9][0-9]-/) {
            printf "%10s\t%-20s\t%10s\t%10s\t%-s\n", $5, $1, $3, $4, $2;
        } else { 
            if ($2 ~ /20[0-9][0-9]-/) {
                printf "%10s\t%-20s\t%10s\t%10s\t%-s\n", $2, $1, $4, $5, $3;
            } else {
                printf "Unknown format:\t%s\n", $0;
            }
        }
    }'
done

Результат вот (третья колонка - цена в центах * 10):

И несколько полезных команд. Запись результатов в файл для дальнейшего анализа:

$ ./bin/apps.sh | tee ~/Documents/apps.txt

Перечень всех бесплатных программ, отсортированный по дате приобретения (“grep -i free” не подходит, в названии платных программ может встречаться “free”, например, программа “WifiTrak (Find FREE WiFi)” стоит $0.99):

$ cat ~/Documents/apps.txt | awk -F '\t' '$4 ~ /F[rR][eE][eE]/ {print $0}' | sort -n

Вариант:

$ cat ~/Documents/apps.txt | awk -F '\t' '$3 == 0 {print $0}' | sort -n

Общее количество программ (я недосчитался 14 программ из 252, но разбираться лень, мне этого достаточно):

$ cat ~/Documents/apps.txt | wc -l

Суммарная стоимость всех программ

$ cat ~/Documents/apps.txt | awk -F '\t' 'BEGIN {sum=0} {sum += $3;} END {printf "Total: $%4.2f\n", sum/1000}'

Распределение количества установленных программ по месяцам (update = purchase, не удивляйтесь):

$ cat ~/Documents/apps.txt | awk -F '\t' '{print $1}' | \
    sed 's/-[0-9]*$//' | sort -n | uniq -c 
   2 2009-03
   3 2009-04
   5 2009-06
   7 2009-07
   6 2009-08
   3 2009-09
   2 2009-10
  10 2009-11
  10 2009-12
   3 2010-01
   3 2010-02
  36 2010-04
  22 2010-05
  73 2010-06
  53 2010-07

И т.д., и т.п. Shell - вещь мощная и всегда под рукой. Желающие могут посмотреть примеры “one-liner’ов” для sed и awk. Более правильно было бы анализировать все данные, подготовив их в Perl/Python/ObjectiveC, но shell более доступен.

Comments