Absolute Beginners: Unix for Art Students – part 3

In what is probably an office space or design studio (you can make out a laser printer, the back of a flatscreen monitor) a text is tacked to the wall constructed of a number of A4 sheets collated together: SEX DIFFERENCES ARE HERE TO STAY

After working through the firsttwoparts of Absolute Beginners: Unix for Art Students Fabien asked me how you can than actually use the terminal to make something. That is a good question. In part 1 glit writes that it is commendable to find a more intimate way of dealing with your computer, but that does not enter the question what you could be doing with your terminal. Taking cues from a design installation we developed for the Performance Studies International festival, I would like to show an example of using the command line to create graphic images, and the kind of design processes that it can accommodate.

Building pipelines

The unix command line is built around passing around text. Programs generate text, and other programs can take this as their input. You can start to create whole ‘œpipelines’ of programs all connected together.

As our input today we take the tweets of Jenny Holzer. I do not know if you’ve heard of her, but Jenny Holzer is an artist who’s work prefigures contemporary social media: long before the advent of Facebook and twitter she has been claiming public space with her written truisms that, like habitus says, always precipitate on the edge between worn clichés and individual confessions (with you inside me comes the knowledge of my own death).

Seeing how Holzer has built her oeuvre and her career around the logic of the status update since well before it existed, it was a small step for her to take her work to twitter.

Today we are not going to visit the twitter website, we are going to access it via the terminal. To get the latest tweet from Jenny Holzer we use the command:

curl "http://twitter.com/statuses/user_timeline/jennyholzer.json?count=1"
curl --silent https://twitter.com/jennyholzer

The output will be something like:

[{"coordinates":null,"truncated":false,"place":null,"geo":null,"in_reply_to_user_id":null,"retweet_count":36,"favorited":false,"in_reply_to_status_id_str":null,"user":{"listed_count":1572,"contributors_enabled":false,"lang":"en","profile_text_color":"000000","protected":false,"location":"","statuses_count":359,"profile_background_image_url":"http:\/\/a0.twimg.com\/images\/themes\/theme1\/bg.png","name":"Jenny Holzer","default_profile":false,"profile_link_color":"D73030","url":"http:\/\/en.wikipedia.org\/wiki\/Jenny_Holzer","utc_offset":-18000,"description":"Abuse of power comes as no surprise.","friends_count":0,"profile_background_color":"D73030","following":true,"profile_background_tile":false,"followers_count":37419,"profile_image_url":"http:\/\/a2.twimg.com\/profile_images\/25643062\/jenny_holzer_normal.jpg","default_profile_image":false,"geo_enabled":false,"created_at":"Wed May 30 19:07:47 +0000 2007","profile_sidebar_fill_color":"F0F0F0","profile_background_image_url_https":"https:\/\/si0.twimg.com\/images\/themes\/theme1\/bg.png","favourites_count":0,"is_translator":false,"show_all_inline_media":false,"follow_request_sent":false,"notifications":false,"profile_sidebar_border_color":"000000","profile_image_url_https":"https:\/\/si0.twimg.com\/profile_images\/25643062\/jenny_holzer_normal.jpg","screen_name":"jennyholzer","id_str":"6451032","verified":false,"id":6451032,"profile_use_background_image":false,"time_zone":"Eastern Time (US & Canada)"},"in_reply_to_screen_name":null,"created_at":"Fri Jan 13 15:34:55 +0000 2012","in_reply_to_user_id_str":null,"retweeted":false,"source":"\u003Ca href=\"http:\/\/twitter.com\/#!\/download\/iphone\" rel=\"nofollow\"\u003ETwitter for iPhone\u003C\/a\u003E","id_str":"157848105683922945","in_reply_to_status_id":null,"id":157848105683922945,"contributors":null,"text":"SEX DIFFERENCES ARE HERE TO STAY"}]

Curl is a program that gets the contents of a document on the web, and prints it out to the terminal.

We have requested the status from twitters API, which is a way for twitter to present the data in a format that is more easy for computer programs to consume. It uses JSON format, which is great and all, but it’s just a little bit to new-fashioned for our means: we want plain old fashioned text.

To go from the JSON to the old fashioned text, we are constructing the first part of our timeline.


curl "http://twitter.com/statuses/user_timeline/jennyholzer.json?count=1" | sed 's/.*"text":"\([^"]*\)".*}]/\1/g'
curl --silent https://twitter.com/jennyholzer | grep -m 1 "tweet-text" | sed 's/.*>\([^<]*\)<.*/\1/g'

The output is:


The | symbol feeds the output from the curl command to the sed command. The exact arguments we are using for sed we will not go into today, because it is a bit daunting if you are just getting into this sort of thing, but it suffices to understand that sed manipulates it input so that everything but the little part inside text=" " is maintained.

Now we have the plain text as output, which we could use as input for another program. For example:

curl "http://twitter.com/statuses/user_timeline/jennyholzer.json?count=1" | sed 's/.*"text":"\([^"]*\)".*}]/\1/g' | figlet
curl --silent https://twitter.com/jennyholzer | grep -m 1 "tweet-text" | sed 's/.*>\([^<]*\)<.*/\1/g' | figlet
 ____  _______  __
/ ___|| ____\ \/ /
\___ \|  _|  \  / 
 ___) | |___ /  \ 
 ____ ___ _____ _____ _____ ____  _____ _   _  ____ _____ ____  
|  _ \_ _|  ___|  ___| ____|  _ \| ____| \ | |/ ___| ____/ ___| 
| | | | || |_  | |_  |  _| | |_) |  _| |  \| | |   |  _| \___ \ 
| |_| | ||  _| |  _| | |___|  _ <| |___| |\  | |___| |___ ___) |
|____/___|_|   |_|   |_____|_| \_\_____|_| \_|\____|_____|____/ 
    _    ____  _____   _   _ _____ ____  _____   _____ ___  
   / \  |  _ \| ____| | | | | ____|  _ \| ____| |_   _/ _ \ 
  / _ \ | |_) |  _|   | |_| |  _| | |_) |  _|     | || | | |
 / ___ \|  _ <| |___  |  _  | |___|  _ <| |___    | || |_| |
/_/   \_\_| \_\_____| |_| |_|_____|_| \_\_____|   |_| \___/ 
 ____ _____  _ __   __
/ ___|_   _|/ \\ \ / /
\___ \ | | / _ \\ V / 
 ___) || |/ ___ \| |  
|____/ |_/_/   \_\_|  

Now we have Jenny Holzer ascii art!

We are going to go a bit further with this. What we want to do is layout this plain text in such a way that we could display it or print it. For this we are going to use a program called pango-view. It comes as part of pango, which we will have to install:

brew install pango

In fact, pango-view, spoils the fun somewhat, because it doesn’t let you use it as part of a pipeline. We’ll have to store the Jenny tweet into a text file:

curl "http://twitter.com/statuses/user_timeline/jennyholzer.json?count=1" | sed 's/.*"text":"\([^"]*\)".*}]/\1/g' > jennytweet.txt
curl --silent https://twitter.com/jennyholzer | grep -m 1 "tweet-text" | sed 's/.*>\([^<]*\)<.*/\1/g' > jennytweet.txt

The > lets you store text output into a file. So we are storing the output of are pipeline, the plain text tweet, into the file jennytweet.txt.

Pango-view lets us lay-out the text and output it as a picture:

pango-view jennytweet.txt -q -o jennytweet.png

‘œSEX DIFFERENCES ARE HERE TO STAY’ set in pango-view’s default font

If you type man pango-view you get an overview of the different options you have. -q, for example suppresses the default behavior to also display the result in a window. -o specifies the output file, in this case jennytweet.png. Next to these two options, we also specify an argument, which is the inputfile to use. The program knows it is an argument instead of option, because it is not preceded by a dash and an option name.

In the man page, we read that we can use --font to specify a font. It does not tell you the format to do so, which is the name followed by the size:

pango-view jennytweet.txt -q -o jennytweet.png --font "Futura 36"


By default, pango-view thinks in pixels. So the Futura will have an x-height of 36 pixels. If we don’t specify any measurement for the width, the text will by laid out on one line like a long banner, the width determined by the width of the text.

If we want to produce the look of a laid-out piece of text, we will have to specify a width:

pango-view jennytweet.txt -q -o jennytweet-laidout.png --font "Futura 36" -w 400

‘œSEX DIFFERENCES ARE HERE TO STAY’ set in Futura, laid out to a maximum width

The cool thing about pango-view is that it can also generate vector files: pdf, but also svg and postscript. You just change the filename, and it does it automatically.

pango-view jennytweet.txt -q -o jennytweet-laidout.ps --font "Futura 36" -w 400

(Check out the resulting file in preview with open jennytweet-laidout.ps.)

Why postscript? Well, we have this really cool old-school postscript utility called poster. And we are going to use this to create a tiling version of the image we just created, that spans many sheets of paper. First install poster:

brew update
brew install poster

(You do no have the brew command? See tellyou’s post about homebrew). To generate a poster, you can do:

poster -s 4.4 jennytweet-laidout.ps > jennyposter.ps

The -s 4.4 scales our original image 4.4 times. The original image has no real size declared in cm, so I did not know beforehand how big the result was going to be. I just came up with this 4.4 value by trail and error.

Voilà. One can open this in preview and print it. Heck, one can even print it from the command line:

lpr jennyposter.ps

Let’s hang it on the wall.


Of course one could have used a vector illustration program to layout this text and print it tiling? I guess the difference is that now we have a pipeline in place… If you run the program a week later, Holzer will have a new tweet in place, and we won’t have to change a thing but we will still get a new poster.

What we did in Utrecht was a variation on this. The workflow as such: dancers go around the conference and post status updates to a private Facebook group. A script checks for new messages, then sends them through pango-view and poster: these are printed on graphing paper. The dancers then return into the space to further interpret their own status messages, in attaching them to the wall.

After alleviating the basic layout to a script you have gained the space to design a social protocol…

Well yeah, but a lot of design decisions are still visual: using the graphing paper, the green dots, the erratic font (the latin characters of a Japanese open source font). Though they all impact the social process in one way or another.

Once your pipelines get more complex, you will usually start to package them in scripts. You can make scripts from a sequence of terminal commands, or you can use any of the computer programming languages that you have available on your system.

The terminal maintains a central place in the unix scheme. This is where you you run commands, including the scripts you have written yourself. It is the go to place for manipulating files, and experimenting with commands.

I wish there were more than just sex differences, perhaps six?

BTW, for this article I was inspired by OSP’s excellent workshop Please Computer Make Me Design. I had been using the terminal but only really got the pipes etc. after I followed this…

jenny holzer is fine, but her mom is better (srsly) http://twitter.com/jennyholzermom

Ah you can also pipe your output to the say program then it will use the Mac’s built in text to speech to read it out to you. Jenny is talking to you!

curl "http://twitter.com/statuses/user_timeline/jennyholzer.json?count=1" | sed 's/.*"text":"\(.*\)"}]/\1/g' | say

So what we also tried with the students is the overlay multiple pdf’s on top of each other. You need to brew install podofo, create a file that lists all the pdf’œs, and in the same folder download a recipe for the imposition: See stdin’s bazaar.


Leave a comment