iPhone and Linux

Sunday, January 31, 2010

Simpler iPhone language pack deletion script

My earlier script is a pain. It works fine but I'm not happy with it because it's too much work keeping up with iPhone developers and their screwy names for the language packs.

For some reason, fr.lproj and French.lproj weren't good enough, so there's some fr_FR.lproj popping up, and not only for French, but a variety of languages. The ISO language code for Spanish is "es," so the language pack should be either "Spanish" or "es," but now I'm seeing "sp", "sp_es" and "es_ES." "Sp" isn't an recognized code for any language.

For a script that essentially greps a list of 60 languages in the old format, I don't want to have to add another 30 to deal with these new names popping up. It's easy to add them to the list, but without rewriting the script, it means the user has to be asked "yes or no" for even more languages.

I never thought it would become a project I had to maintain anyway. I will rewrite it so that it's flexible and can handle new languages on it's own, and to lessen the number of times the user has to say yes to each language, but here is a simpler script to use for the time being.

Since most people want to remove everything except English and Japanese anyway, this simple script will do that. It only asks one question "Do you want to delete everything except English and Japanese?" and if you say yes, it does it. It won't have any problem with new language codes because it gets a list of all languages, filters out English and Japanese and deletes everything that is left. Simple. Almost as simple as my very first post on the subject.


#! /bin/sh
# Thu Feb 4 2010
if [ `id -u` != 0 ]; then echo "Oops, you need to be root to run this script"; exit 0; fi
while [[ $choice != 'y' ]] && [[ $choice != 'n' ]]
echo "Do you want to delete all language packs
except English and Japanese (for emoji
y or n?"
read choice
if [[ $choice = 'y' ]]; then
echo "Please wait while I delete the chosen
language packs. This may take a minute
or two..."
updatedb && locate lproj | grep -E lproj$ | grep -v -i ja | grep -v -i English | grep -v -i \/en > .deletelist_fubaya
while read file; do rm -rf "$file"; done < .deletelist_fubaya
num=$(cat .deletelist_fubaya | wc -l)
rm .deletelist_fubaya
echo "$num language pack directories deleted"
[[ $choice = 'n' ]] && echo "Ok, I won't delete anything."; exit 0
# end of script

Friday, January 29, 2010

Copy and paste in MobileTerminal

I've been using this "paste" script for a long time, but put off creating anything to copy as I didn't have much of a need. I finally got interested when it came up on a forum last night. Here is the first draft of working copy and paste.

Both scripts require PasteBaordStacker because, as I have mentioned before, it stores everything as plain text and I've never gotten around to deciphering Apple's PasteBoard.

Paste also requires awk. The awk line may be familiar, it has been so useful it's probably in half the scripts on this blog. Copy uses sed, but I think sed is already installed on a jailbroken iPhone.

Edit Feb 7 2010: added the sed lines to convert the characters <, >, and & which get automatically encoded.

#! /bin/sh
awk 'BEGIN{ RS="</string>"}{gsub(/.*<string>/,"");print;exit}' $file | sed '

#! /bin/sh
in=$(cat -)
text=$(echo '<string>'"$in"'</string>')
sed -i "7i\\
$text" $file

Paste can be used in a variety of ways, but there are two standard methods that are most useful. 1) You can type "paste" on the command line and it will output the last thing you copied on the system. 2) You can use it in a subshell to paste an argument to another program. Example, copy a link to a file in Safari then type wget $(paste) in Terminal. Since the subshell is executed first, the resulting command that is executed is wget www.example.com/file.txt

Copy is a little rough. Since I used PasteBoardStacker, that means text isn't copied directly into the Apple PasteBoard. You have to select the text in PasteBoardStacker first, which is done by double tapping the status bar, then tapping the text you want from the pop-up list. It takes an extra step but it's still a good way to copy text from Terminal, and other than directing the output to a file, opening it and copying, it's the only way I am aware of. Copy handles piped input so if you run this command: echo "Hello world" | copy, you can then select "Hello world" in PasteBoardStacker and paste into another app.

Copy also requires you to escape some special characters with a backslash. echo "Hello world!" | copy won't work because the shell will try to interpret the exclamation point. echo "Hello world\!" | copy is what you need to use. Edit: D'oh, this was a poor example because it's normal shell behavior and not related to copy, but the sed line in copy still can't handle some characters like "<"without escaping.

Friday, January 22, 2010

iPhone/Linux "Network Printing"

This hack may be useful if you have a non-network printer attached to your Linux box and want to print text remotely from your iPhone.

There are actually several ways to accomplish this. You can simply create a text file and scp that file to your linux box, or pipe it over ssh then execute a print command, but neither worked right for me. The first requires you to create the text file, put something in it, save, then send to print. As for the second method, I can't get text to pipe over ssh from my phone like it should, and even if I could, I'm not certain it would work with slogin and ssh keys. Nothing seemed to work for me, so I went with tapping an icon to automatically print the clipboard contents. This way, you don't have to fool with any files, and if you do want to print a file, you can open it, copy the text, and print it.

On the iPhone, you need PasteBoardStacker and ssh (preferrably set up with ssh keys). PasteBoardStacker is used because it's easy to get the plain text from it and I've never gotten around to decoding the Apple pasteboard. Maybe I'll tackle that one someday.

On your Linux box, you need a to be able to print from the command line, which should already be possible as long as your printer works. In my example, I also use enscript to format the text before piping the text to the lpr print command. Enscript should be present on most systems, and I can't imagine anyone actually prints text that isn't word wrapped.

Here is the script that goes on the phone. If you want to run it by tapping an icon on SpringBoard, you need to set up ssh keys and follow these directions. If you want to run it from MobileTerminal and type your ssh password in every time, change the scp line to "scp ispool USER@IP:/PATH/TO/PUT/FILE." This script can be named anything you like. (Update: I changed the first command, which was really long, to make two shorter lines)
#! /bin/sh
cd /var/mobile
text=$(awk 'BEGIN{ RS="</string>"}{gsub(/.*<string>/,"");print;exit}' $file | sed '
echo $text | tr -d  > ispool
scp -i ~/.ssh/KEYFILE ./ispool USER@IP:/PATH/TO/PUT/FILE
rm ispool
ssh USER@IP iprint

This goes on the Linux box and is called "iprint." If you want to name it something else, change "iprint" on the last line of the previous script to the new name. This uses enscript, but that's optional and you can change that whole line to "cat ispool | lpr" if you like.

#! /bin/sh
cat ispool | enscript -h -B -1 --word-wrap --media=A4
rm ispool

Or, if you would like a Prowl notification of the print job...
#! /bin/sh
cat ispool | enscript -h -B -1 --word-wrap --media=A4> tmpspool 2>&1
job=$(cat ispool)
output=$(cat tmpspool)
rm ispool tmpspool
curl -k https://prowl.weks.net/publicapi/add -F apikey=xxxxx -F application="Print job:" -F description="$output $job"

Update: I found that piping over ssh does work as it should. I don't know why it wasn't working for me the other day, except maybe because I was figuring out this whole print thing at 2 in the morning. That's what happens when you lay in bed and think "I'd like to print this out but don't want to get up." Anyway, this script can be ran on the phone to print the contents of the clipboard. I still like the above method because it allow me to get the output via Prowl notification, but this is simpler:
#! /bin/sh
text=$(awk 'BEGIN{ RS="</string>"}{gsub(/.*<string>/,"");print;exit}' $file

echo $text | tr -d  | slogin -i ~/.ssh/KEYFILE USER@IP lpr

Blog Archive