Can't snow a snowman...and my middle name's Frosty!

<< Previous Page :: Next Page >>

Obscure Linux Commands: Cheating At Word Games

Date/Time Permalink: 09/24/07 07:25:30 pm
Category: HOWTOs and Guides

Now, granted, cheating at word games won't make you very good at the word games. However, using practical problems from word games is an excellent opportunity to brush up on your Command-Line-Foo! There is no better exercise to master regexps.

One thing you've probably found is that 99% of Linux distros have a file in /usr/share/dict/ which is called "words". True to Unix traditions, it's nothing but a plain text file of words, one per line, which is what the system uses for spell-checking.

So, you're bumbling along doing a crossword puzzle, and you need to find a seven-letter word that begins with 'm', ends in 's', and has a 't' in the middle. Go get it, grep!

ß grep "^m..t..s$" /usr/share/dict/words
mantels
mantles
martyrs
masters
matters
mentors
misters
mittens
mortals
mortars
mottoes
mouthes
mutters
mystics

Blow by blow:

  • ^ - The carat (shift-6) says "this is the beginning of the line". Without it, it would find all words like "fundamentals".
  • $ - The dollar sign is the same thing, only for the end of the line. Without it, you'd also get words like "mattresses".
  • . - The period means "any character here". One, and one only, character will match here.

But suppose you're dealing with a game besides a crossword puzzle, like Scrabble for instance, and you're limited by more constraints than in a crossword. You might want to 'hook' (Scrabble lingo for 'add letters to the beginning or end of a word to form more words'). So, let's see how many words end in "are".

ß grep "are$" /usr/share/dict/words | wc -l
43

Well, those are good odds. But we hit the edge of the board with some of them (I peeked). So, we need words that are seven letters or less which end in "are". "^....are$" would get all of the seven letter words, but not the shorter ones. The solution is rather cryptic this time:

ß grep "^.\{1,4\}are$" /usr/share/dict/words
airfare
aware
bare
beware
blare
care
compare
dare
declare
ensnare
fanfare
fare
flare
glare
hare
mare
pare
prepare
rare
scare
share
snare
spare
square
stare
unaware
ware
warfare
welfare

...but we've met the caret, dollar sign, and period before, so really the new part is the \{1,4\}. This says "match as few as one, and as many as four, repetitions of the previous character". The activator for the number range is the curly braces, which then have to be escaped with slashes (does anybody know why, class?). And since the previous character is a period, which matches any letter, we've found all the words shorter than eight letters which end in "are".

This is all well and good, but we only have so many letters to work with in Scrabble at one time. Say that our current rack has the letters "C F T W A B M". Can we limit it to only words which use those letters?

ß grep "^[cftwabm]\{1,4\}are$" /usr/share/dict/words
aware
bare
care
fare
mare
ware

Ah, now we're getting somewhere! The [] square brackets give the set of acceptable characters. Another way to use them is to express a range (e. g. [0-9]), but that's hardly the usual case in word games.

Here's another kind of word game you can play online. It's called simply "Crossword", but it's not at all like a regular crossword. Instead, you have to fill letters into a partially-completed grid, using only the letter provided. If you have a four letter space with "_w_y" and the 'A' available, you click on one of the empty slots which will then light up every space on the board that uses the same letter, click on A, and it will put the letter A everywhere in the puzzle that's marked for the same letter. And so on to complete the puzzle.

I introduce this fun little diversion because it brings up still other kinds of problems to solve. As you progress to higher levels in this game, you eventually come to a problem like "All I know about this word is that it has seven letters and the first, fourth, and fifth letters are the same. What is it?" I'll bet even the regexp gurus are scratching their heads at this point....

I'll give you a minute if you want to solve it yourself.

Hint: you ain't gonna do it with regexps alone this time.

OK, here's the spoiler:

ß grep "^.......$" /usr/share/dict/words | \
> awk '{$W==$1; FS=""; if ($1==$4 && $4==$5) print $W;}'
blabbed
blubber
esteems
exceeds
scissor
twitter

That's right, we had to use some real programming. Any Perl Ninjas out there have a solution in fewer keystrokes, you're welcome to post it. I know you're dying to.

What we did is simply grep for all the seven-letter words. Then the awk part (a) first grabs the whole word as "$1" and sticks it into the variable $W for 'word', (b) declares field-separator (the built-in FS variable) as null so it treats each character as a field, then (c) recycles $1, along with $4 and $5, as individual letters within the word, (the first, fourth, and fifth). So the last awk statement tests the equality of those three letters, and only prints the word (still safe in $W) if the match test passes.

Last, here's a bonus program: an. If you don't have an (it's rare to find it included in a base system) you can pick it up here in the Debian archive. If you have a non-Debian system, look for the source tarball in the right-hand column of that page. It compiled on my Slackware in nothing flat.

When installed, an takes your quoted string and returns all the possible anagrams for that string.

ß an "Richard Stallman"
marshal card lint
marshal clan dirt
thrills card an am
thrills cram ad an
thrills can drama
... and etc.

And it will only return dictionary words! It's pretty fast, too. Just the thing for finding "bingos" in Scrabble, as well as basis for nutty conspiracy theories.

I found it amusing that Richard Stallman's name breaks down to "chill drama rants", amongst others... the first hit for "George Bush" is "buggers hoe" and another one is "here go bugs". Endless hilarity potential.

sign guy sig

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

Arcane Linux Commands: dc

Date/Time Permalink: 09/20/07 02:34:48 pm
Category: HOWTOs and Guides

If anybody within earshot of you is struggling to learn sed and ever remarks "This is like learning Klingon! Could they make it any more cryptic?", you can always point them to dc.

dc is the command-line Unix "Reverse-Polish Notation"(RPN) calculator. The name stands for "desktop calculator". OK, so what is a Polish calculator and why would you want to reverse one? The math that you do in school uses infix notation, with the operator between the numbers (3 + 5). Prefix notation puts the operator first (+ 3 5) and is what the Lisp language uses. The prefix notation is known as "Polish notation" after the nationality of Jan Łukasiewicz who invented it. Postfix notation, then, has the operator at the rear (3 5 +), and so is also the reverse of Polish notation.

What's the difference? In computer programming, you have to specify what order you want a multi-part calculation to be in. Everybody is familiar with the old problem of A*B-C. For A=5, B=3, C=2, multiplying first and subtracting second gives you 13, while subtracting first and multiplying second gives you 5. To specify which operations you want performed first, you have to either memorize the complex orders of operations (which change from one language to the next) or use a lot of parenthesis ((A*B)-C) or (A*(B-C)). Hey, that's what everybody complains about in all those languages that use parenthesis!

In dc, we eliminate the problem this way:

dc -e '5 3 * 2 - p'

...gives 13, and

dc -e '5 3 2 - * p'

...gives 5. What's going on here is that it uses a "push-n-pop" stack, a data-storage system familiar to programmers of Assembly and Lisp. When you enter a number, it gets pushed onto the stack. When you enter an operator or a command, it pops the latest affected numbers off the stack, performs the operation, and pushes the answer back onto the stack. The commands (which are all single-letter) have various other effects.

Reading through "info dc" on the command line will give you the commands of dc, but will do little to help you grasp the unfamiliar concepts if you aren't used to using an RPN calculator. So consider this post to be the supplemental reading to the dc info section (or the dc man page).

Let's look at one of the reasons to use dc as opposed to the Bash echo command or Python: you can set the floating-point precision easily. The command to do that is "k" (first thing you thought of, right? It stands for krecision!) and it takes the most-recently-pushed number as an argument. So you can say "2 k" to set the precision to two decimal places for dollars-and-cents operations. While we're at it, let's introduce the "v" command, which computes a square root. This makes sense if you've seen it in ASCII art:

 ___
v 2

So, the dc way to get the square root of two to ten decimal places is:

ß dc -e '10k2vp'

which gives back 1.4142135623 and returns you to a prompt, lickety-split. We could also make it less confusing by using spaces:

ß dc -e '10 k 2 v p'

That's "10... set this as the precision... 2... calculate this number's square root... print the result".

The only time you need to use spaces is to separate two numbers (so 10 and 30 don't become 'one-thousand-and-thirty'). For that matter, you can also run dc interactively. The "-e" thingie says to evaluate the expression (and exit immediately). But check out this session:

ß dc
10
k
2
v
p
1.4142135623
q

...the "q" is the command to quit. Since you can also omit spaces in interactive mode, we could also go:

ß dc
10k
2vp
1.4142135623
q

Story problem: Johnny is taking a contract to write 20 articles @ 600 words each, for which he intends to charge 2¢ per word. How much money will the client pay?

ß dc -e '2k20 600*0.02*p'
240.00

And we're going to add one more command: "f" dumps the whole dang tootin' main stack to the screen, instead of just printing the first value.

dc also has a memory feature. You can call the memory 'R' (register?) and this is of course another stack. So you can store a value for later use. Pop a value off of the main stack and push it onto the R stack with "sR" and pop the value back off the 'R' stack and push it back onto the main stack with "LR". To copy the value off the register stack (as opposed to moving it) you say "lR". By the way, registers can have ANY single-letter name you want! But they have to be initialized first before they are used (with a command like "sR"). Puzzled frowns? Here, my pupils:

ß dc
1000
sZ
f
lZ
f
1000
sq
f
lq
f
1000
lZ
f
1000
1000
lQ
dc: register 'Q' (0121) is empty
q

Let's experiment with the previous calculation, using this new knowledge:

ß dc
2k20 600*0.02*sRlR
f
240.00
lR 0.15*f
36.00
240.00
-f
204.00

What we did: the previous word-count problem, pushed it to Register, copied it back, printed the stack to show where we are, multiplied the Register times 15% and pushed it onto the stack and showed the stack again, then subtracted the second value from the first value and showed the stack again.

Story problem #2: Johnny is taking a contract to write 20 articles @ 600 words each, for which he intends to charge 2¢ per word. Johnny's agent charges 15% commission for finding him these jobs. What is Johnny's take-home before taxes?

ß dc -e '2k20 600*0.02*sRlRlR0.15*-p'
204.00

Feel free to indulge in some primal scream therapy, not only at Johnny's ridiculously low income, but at the fantastically terse command he used to figure it. The other beauty of dc is that it is a relatively powerful calculator (supporting +*-/ (standard four functions) % (modulus) ~ (division and remainder) ^ (exponent) | (modular exponent) and v (square root)) which can be included in a script or command line. It can also do base-conversions on-the-fly with the "i" (input radix) and "o" (output radix) commands.

So, 256 in hexadecimal is:

ß dc -e '16o256p'
100

While hex FFFF in decimal is:

ß dc -e '16iFFFFp'
65535

So, it has many uses in scripting.

Hope you got something out of this little tutorial, and now for some links:

Wikipedia dc page
dc man page online, hosted by "Bash Cures Cancer".
Advanced Bash Scripting Guide (aka "the Bible") uses dc in a couple of script examples about half-way down. Also shows some of bc, dc's friendly companion.
Everything2's node on dc It gets around to the Unix command at the middle-to-bottom. Notable for having FizzBuzz in dc (horrors!!!)

tattoo sig

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

Writers-Block Busters for Bloggers

Date/Time Permalink: 08/25/07 12:09:17 pm
Category: HOWTOs and Guides

Eh, it isn't really a geek HOWTO, but a lot of geeks blog, too. And the formatting's funny because I wrote it in Emacs with hard line breaks. Because sometimes I just like to.

If I had a nickel for every time I've read one of those "top ten ways
to beat writer's block" articles, I'd have a cheap, trite
metaphor. Well, here's my own list for finding the start button on the
writing machine in your head, and even how to oil it up occasionally.

1> The - THE! - most important thing I can tell you about writing
is this: If the text is not fun to write, it will not be fun to read.

I can apply this test to a piece of writing and tell instantly whether
the author was a burned-out zombie shuddering with every line they
typed, or whether they were chuckling and gibbering as they zipped
along composing their brilliantly inspired piece. Use this to help
yourself: make writing as fun as you can, always.

For everyone, point number one needs to be amplified. Don't get angry
at what I'm about to say; it's just words on a page. But this is
iron-clad truth, and you can either accept it or leave because I'm
wasting your time. The iron-clad truth extending from point #1 is:

          IF YOU NEVER ENJOY WRITING AT ALL,
            THEN YOU SUCK AT WRITING.

There's almost nothing you can do about that.

2> Store nuts for the winter - Whenever any silly idea is popping
into your head, jot it down. Save a big old folder of pieces you
started when anything interested occurs to you. You should never ask,
"What will I do with this?" You should just jot down that idea, plan,
rant, joke, funny phrase, or cool new word you've just learned, and
then afterward ask, "How can I use this?" Turn your inspiration to the
task, instead of starting with the task and trying to find inspiration
from there.

3> Vary your hangouts like a cat. - Every now and then, try to
write using a different program, different computer, a notebook in a
cafe, a cocktail napkin in a smoky bar, a change of office, a
different chair, anything. Monotony breeds boredom. Especially writers
tend to suffer from the "same four walls" syndrome, because left to
their own devices a writer will live like a potted plant.

4> Use our feet to wind up your brain. - It's a cliche that people
get their best ideas in the shower. But try this: try pretending you
are a street mime and, clothed and dry, pretend to take a shower while
not in the shower. What did you do? You stood up and moved around, and
stayed on your feet for a few minutes! That's actually what's going on
in the shower. That and it's also private, so there's fewer
distractions.

Taking a walk always does it for me. Driving doesn't count. Evolution
has wired it into us since the wide savanna to stay on the move. Our
brains really do work better when our bodies are in motion. Either get
out and trot to the store, visit your back yard, or just roam around
the house and let your feet and mind wander.

5> Put your brain on time-out. - The Buddhists say "The mind is a
monkey"; have you thought that maybe the reason why your mind is
blocked is because you've indulged it into being an inattentive slug?
So sometimes, force a time-out period, deliberately not
thinking. Meditation is fine if you know how, but it's not
necessary. Do housework, run some errands, or other trivial
activity. Deliberately watching something mindless on television also
works. But set a time limit, and come back in an hour. Now is your
mind ready to work on the task?

6> Get inspiration from the funniest thing you can find. - In
addition to the usual advice to read better authors for inspiration, I
find that it is especially invigorating to read or watch something
funny. Not just mildly amusing, but screaming funny. Laughter makes a
chemical reaction in your brain. It will get you going.

7> When all else fails, write about your block! - In rare cases,
you might be blocked because the subject or assignment just isn't any
fun. So start out writing a paragraph identifying with the reader
about why it is such a hard subject to tackle. Ridicule the
subject. Criticize the previous literature on the subject. Scold
yourself for not being able to find a handle on it. This is a sneaky
sideways approach, but it will eventually lead into a hook where you
at last do what you were supposed to do, which is write about the
subject!

8> Write about something else entirely. - project be damned,
sometimes you want to write about what is interesting to you. So get
it out of your system. Completely turn off all thinking about the
project at hand - the writing you have to do - and indulge in the
writing you want to do. You might be able to lead this back to the
task. Maybe work it into the project, continue an idea from your
desert article back into your main course article, draw on the
activity period for inspiration, or just get back into the zone. Like
#7, this idea sometimes works in rare situations.
Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

HOWTO create keyboard macros in Emacs

Date/Time Permalink: 04/29/07 12:04:04 pm
Category: HOWTOs and Guides

You hear about the great macro feature of Emacs all the time. You see cheat sheets for Emacs key combinations all the time. But you never quite see the keyboard macro trick demonstrated clearly. Here's how it works:

You begin with "C-x (" - that's Control+X, then shift-9. The message buffer will say "Defining kbd macro..." Then you type in whatever series of keystrokes you will want to call with one keystroke. When you're done with the series, hit "C-x )" (open and close parenthesis, just like Lisp, get it?) and the message buffer will now say "Keyboard macro defined". Now you can call the macro at any time with "C-x e" and it will execute just like you typed it all in from scratch!

A real-world (set-up!) example:

Ugh! My lousy HTML editor formatted my code listing example wrong! I want to get rid of the paragraph tags so I can just wrap the code in "pre" tags instead. I have a bunch of places where this happens in the file, and I'm looking to spend all day deleting "<p>" and "</p>" tags:

   <p></p>
   <p>;; Factorial function</p>
   <p></p>
   <p>(defun factorial (n)</p>
   <p>(if (<= n 1) 1</p>
   <p>(* n (factorial (- n 1)))))</p>
   <p></p>

First (I'm working in XEmacs), I hold down shift+arrow keys to highlight the block I want to affect. Now before I type my key sequence, I just throw in a "C-x (".

My key sequence will be:

  • M-x replace-regexp
  • </?p>
  • :return: x2 (I want them replaced with "nothing"!)

This will strip both "<p>" and "</p>" tags from the block:

   ;; Factorial function
   
   (defun factorial (n)
   (if (<= n 1) 1
   (* n (factorial (- n 1)))))

Happy ending, but don't forget to type "C-x )" now to end the macro! Now I can go to all the other code blocks and highlight them, hit "C-x e", and the bad tags vanish.

vi users, I'm sure you have a way to do this too, but the sed sequence escapes me...

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

HOWTO Play With Your Old QBasic Programs on Linux

Date/Time Permalink: 03/31/07 01:21:43 pm
Category: HOWTOs and Guides

Most any geek who was a kid in the 80's played with BASIC at some point. And the BASIC language with one of the biggest followings is Microsoft QBasic - Microsoft's sole nod to the hobbyist programmer community. Dozens of online sites exist today that are devoted to QBasic, Quick Basic, and Basica, existing in much the same spheres as the surviving BBS/ ANSI art culture. If you still have some old floppies with archives of BASIC programs from your juvenile years which you'd like to revisit, here's how to do it on a Linux box:

Step 1: Get a copy of DOSbox. DOSbox is a no-brainer to install and set up, with its main dependency being the SDL library. Once you have that in, I recommend creating a directory named /DOS/ under your home directory - note that this is a plain old ext2 (or whatever you have set up) file system directory, you don't need to create a special FAT or DOS partition. Thereafter, starting your simulated DOS environment will involve starting DOSbox, typing "mount c ~/DOS/", then typing "c:", and you can then type "dir" to see that you're in your simulated "C:\" drive. Wasn't that easy?

Step 2: Find a QBasic version to download! Here's one. This is tricky - these sites come and go, and Microsoft, which hasn't supported QBasic for centuries, plays peek-a-boo with these DOS legacy program downloads all the time - it's a 50/50 break whether you can get the Microsoft site or an MS Windows system to admit that QBasic ever existed. Rumors abound of hidden folders on install disks. The last version goes by the string "QB45.ZIP" and when you've hunted it down, unzip it to a folder in your /DOS/ directory.

Next you have to format two floppies as DOS and write the disk packages to each. After that, mount the disks in the usual way in Linux, then 'mount' them in DOSbox with "mount a" and your floppy directory, then mount your "C:\" drive, cd to the A:\ directory and run "SETUP.EXE". Follow directions from there. NOTE: As Max Atkin points out in the comments, you can also have the disk images in your directory path and mount them that way without physical floppies.

Step 3: I didn't even bother with installing the second disk, since I'm not interested in making any more binary .EXE files, and the second disk is mainly support for the compiler. QB.EXE runs just fine with the install from disk one, and will be able to read your .BAS files. You can try out the demo BASIC programs included in the "EXAMPLES" directory. Everything works just like you remember, with your embarrassing old graphics demos and munchkin hax running in glorious 640x480 16 mode.

QB screenshot 1
A Mandelbrot demo from the example programs.

QB screenshot 2
One of my graphic demos.

UPDATE: Years after I posted this, I got into Flash toys, and this same idea is now implemented as "circlerama" in the sidebar to right right of this page.

QB screenshot 3
A hilarious drawing program I did, because I missed the old Apple MacDraw drawing mirrors feature so much.

UPDATE: Likewise, the same story goes for the Flash toy "drawdemon", also in the sidebar.

QB screenshot 4
The splash screen to an old tank shooter game I did. You aren't missing a thing by not playing it, believe me!

QB screenshot 5
Who didn't do a hangman game in their learning days?

QB screenshot 6
A draw poker demo game I did. Yes, I drew each card in my own invented bitmap format, saved as plain data files, because QBasic back then didn't have a way to display bitmaps that I was aware of.

Step 4: Thank your lucky stars that you've come a long way since these days!

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

Five X Windows Background Hacks You Probably Didn't Know

Date/Time Permalink: 02/10/07 02:05:30 am
Category: HOWTOs and Guides

Every now and then I stumble upon a nifty little desktop background hack, and after noting them down for a few months, discovered I had enough to make a blog post.

All of these will be variably available here and there on POSIX Unix-like systems. But some distros may not include any of them! The solid color declarations come from a file most X windows setups should have, rgb.txt, which should be in /usr/X11R6/lib/X11/. Have a cat through it to see what declared colors you can use.

To start with the easiest. This is part of the Fluxbox system, and is mostly an interpretation of xsetroot. This program adds the gradient function.

background image screenshot

fbsetroot -solid gray40

Will set a neutral shade of solid gray.

background image screenshot

fbsetroot -mod 12 12 -bg black -fg green4

This will make a tight boxed pattern of black and green.

background image screenshot

fbsetroot -gradient pipecross -from black -to blue

This is an example of the gradient. If fbsetroot is on your system, then "man fbsetroot" will show all the gradient arguments.

This is part of the "xv" program, the really funky old shareware graphics program by John Bradley, last heard from in 1994. It's still hanging around on some Linux systems.

background image screenshot

bggen 0 0 0 255 255 255 | xv -root -quit -

A simple gradient.

background image screenshot

bggen black darkred black -h 128 -w 128 -r 45 | xv -root -quit -

A wild gradient square pattern.

background image screenshot

bggen black gray -r 45 -g 64x64 | xv -root -quit -rmode 3 -

A diamond pattern.

background image screenshot

bggen black red yellow green blue purple black | xv -root -quit -

A full-spectrum rainbow!

Image Magick is a full suite of programs all by itself. Practically guaranteed to be on most distros. There is enough to it to fill a manual on its own, but here is one example:

background image screenshot

convert -size 230x100 xc:black -fill white -pointsize 72 \
-draw "text 25,75 'Linux'" -shade 120x45 im_text.png \
&& display -window root im_text.png

This will create a simple Linux logo and tile it, with a file saved as "im_text.png" in the current directory.

An animated desktop! This is the fractal-generating program. It's a toss-up whether you have it or not.

background image screenshot

xaos -root -loadexample -autopilot

Will load a random xaos configuration file from /usr/local/share/XaoS/examples/, then zoom and pan around in it on autopilot. All desktop functions work normally, just with a moving background! Of course, if you pick up the xaos mini-language, you can create whole demos this way.

More animated desktops! Still hanging around on most systems, this is the simpler precursor to xscreensaver. It also sometimes goes by the name of "xlockmore". There is a multitude of screen hacks that come with it, see "man xlock" for more.

background image screenshot

xlock -nolock -mode matrix -inroot

The Matrix!

background image screenshot

xlock -nolock -mode deco -count 10 -inroot

Hideous rectangles.

background image screenshot

xlock -nolock -mode clock -inroot

An animated, analog clock.

background image screenshot

xlock -nolock -mode tetris -size 40 -inroot

The desktop plays Tetris with itself, and loses a lot.

Lacking that, xscreensaver itself can be run in the root window. Just go to a console and do a "ls /usr/libexec/xscreensaver/" and there are all the screen hacks! Run any one in your root with the -root parameter.

Example:
background image screenshot

/usr/libexec/xscreensaver/kumppa -root

will run 'kumppa' in your background until you kill it with Ctrl-C.

Silly Warning

UPDATE: GeekHacks also tells you how to set a specific example of the GLMatrix screensaver, and have it launch automatically when you log in.

UPDATE 9/14/07: Well, now that it's all over StumbleUpon, I'll add screenshots!

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

HOWTO fix filenames on Linux

Date/Time Permalink: 02/01/07 01:00:44 pm
Category: HOWTOs and Guides

A while back, I posted the Bash for-loop one-liner for batch file operations from the command line. Handy though it is, it has limited applications.

I work online, and have to share a lot of files back and forth with clients. A problem that comes up frequently is when a Windows user sends me a glob of files which have spaces in the file names, along with the standard ALL-UPPERCASE characters and ridiculous punctuation characters. It's the Microsoft file system's way of mangling file sharing for everybody just like their web browser mangles web pages. One-liner loops don't always solve the problem cleanly.

But no sweat; here's the Bash script I cobbled up to safely replace spaces with underscores in whatever directory the ugly things pop up:


#!/bin/bash

ls > /tmp/list
# we have to make the list file in a separate 
# directory so that it doesn't get included 
# in the list of the current directory!
mv /tmp/list ./list
cat list | tr ' ' '_' > listnew
# this turns spaces into underscores
FILE_COUNT=$(wc -l list | awk '{print $1}')
LOOP=1
while [ "$LOOP" -le "$FILE_COUNT" ]
do
  AWKFEED="FNR=="$LOOP
# the command to feed awk
# output will be 'FNR==1', 'FNR==2', ..
  OLDFILE=$(awk $AWKFEED list)
  NEWFILE=$(awk $AWKFEED listnew)
  mv "$OLDFILE" "$NEWFILE"
# keep the quotes to make the shell read file 
# names with spaces as one file
  LOOP=$(($LOOP+1))
done

rm list
rm listnew

exit 0

Quite a messy problem, and to my knowledge there is no one-line fix. (Well, you *could* do it in one line, but ugh!)

Calling your attention to a few highlights: the line calling "tr ' ' '_'" swaps spaces for underscores. You can change this with any other annoying characters you get (like bangs (!)) and the preferred character, or make multiple calls to tr in the same line. For that matter, the one-liner fix examples I gave earlier would knock out most cases of UPPERCASE names and other annoyances. This is just the most optimal solution I could come up with for spaces.

Having thus rendered the barbaric output of lesser systems into something more well-behaved, we may then go on with life in our civilized file environment. *sniff*

animated neon sign image

NOTE: If you're wondering why we Linux types get into such a snit over spaces, see why spaces in pathnames are a dumb idea.

Another update note: Not everybody cares what their file names look like. It is more of an aesthetic issue. Which filename is easier to read, "%233NEW%20YORK%21.jpg" or "New_York_3.jpg"? This also bothers command-line cavemen like me more than desktop-only users. For one thing, a standard file naming system makes it easier to automate file management tasks with scripts!

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

So You're Curious About Linux...

Date/Time Permalink: 01/21/07 12:45:48 pm
Category: HOWTOs and Guides

Every now and then I make a personal acquaintance with somebody who's never seen Linux, but has heard of it. They want to know what it's like and should they try it. I always find myself making the same speech, and I figure lots of other Linux users do too. So here is my canonical About Linux speech. Feel free to clip and save so you have it all in one place for you to point to:

First off, even as a die-hard Technology Freedom paladin, I always tell people that Linux is not for everyone. Specifically, if all you use a computer for is to surf the web and play games - in other words, if a computer is nothing to you but an entertainment device - , Linux won't make much of a difference to you and in the case of games may be a headache; and in fact I should wonder why you bother to own a computer at all when a nice gaming console and a cell phone will provide all the functionality, none of the headache, and be less expensive.

You will most likely have difficulty with Linux if you are below the age of 25 or so (as of 2007). This is "Generation Microsoft" Ω, which was born and raised under the monopoly and has known nothing else. If you've never used anything but Microsoft, you're going to come to a computer with a bunch of preconceived falsehoods that are going to get in your way. And the truth is that Microsoft actually came very late to the operating system game; they were originally a programming language company who kind of scoffed at the idea of a graphical user interface and selling an operating system as a product. Apple, Unix, IBM, Xerox, Commodore/Amiga, and countless others were already well established in computers and doing nicely before Bill Gates even showed up on the scene.

Linux is based on Unix, and so it behaves like Unix. If you had exposure to computers before your first copy of Microsoft Windows, you will find it easier to understand Unix systems. Unix, as time and experience has shown, is really the right way for a computer to function. Different from Microsoft, Apple's OS X system runs a Unix implementation under the surface, Sun's Solaris is a Unix variant, BSD is another Unix variant (and currently exactly twice Linux's age!), and in fact Linux and other Unix variants have become standard in every computer device, from servers to cell phones. The only exception is the home and cubicle-office desktop machine. We already knew what we were doing before some uppity millionaire came along and tried to take over the market. So, all of your complaints about how Unix isn't "just like Windows" will be a waste of time. Unix is Unix for very good reasons. It is Microsoft which is the nonconformist.

To get into Linux, your very best option is to obtain a bootable live CD. You can download them free all day and burn them to CD, or get them from the back of a book about Linux, or have a friend share one with you. A live CD treats your CD-ROM drive (and RAM memory) as if it were the whole computer, and so you can boot Linux and run it as if it were installed, without touching your hard drive and without disturbing your current system and its files. The beauty of this is that you can run risk-free! You can boot up the CD and play around with it at your leisure, without any pressure to learn it all right away.

Probably your biggest difficulty will be getting to grips with the huge variety of GNU/Linux software. If you feel overwhelmed in a Linux environment, it is because you have ten times as much operating system as what you're used to. It is, after all, free, and licensed to the public so that anybody can rewrite it, update it, put their personal stamp on it, re-release it, and port it to other platforms. There is no such thing as abandonware in the Linux world, there are just projects currently lacking an active developer. This has a side benefit: learn a core Unix program today, and forty years from now it will still be relevant. The Linux learning curve is steep, but you only have to climb it once.

Today's Linux systems have evolved through the free software process into the most sophisticated software around. The day is gone when Linux was "for geeks only" - today there are beginner distros which go to great lengths to hide ugly command lines and system driver tweaking from your notice, contrary to what some FUD-sayers would have you believe. If at all possible, find a nearby person (as opposed to somebody you know through the Internet), to sit down and tutor you through a lesson or two about the system. It's amazing how much one-on-one experience helps in learning a system.

Another thing that you will need to get used to: GNU, Linux, BSD, and other free systems are based on the ideal of absolute computing liberty. So the system is designed not just to be used, but to be molded by anybody. Compilers and interpreters are everywhere; there's a programming language every two feet. Configurations are done in plain text files, source code is open and generously documented, and there are buttons and switches all over of which you will only have the faintest idea how to use.

The system is open for you to explore endlessly, like a car with the engine exposed. So remember that even though it isn't geek-required, it is very, very geek-friendly. This also means that if you have a problem, the chances are good that somebody, somewhere else has had the same problem and already found a solution. You don't have to be a programmer to run Linux, but you will find yourself rubbing elbows with a lot of programmers in the Linux community. This is the effect of the idea of technology freedom, erasing the line between user and developer, between owner and customer, and between newbie and engineer. Try to not see this as being intimidating, but rather as complimenting your intelligence instead of insulting it.

Lastly, give yourself a chance. I can't count the number of people I've met who have said that they were computer-illiterate, until they had a chance to explore computers and discovered that they really weren't dumb about technology after all! So take your time, explore the system, sample a few different flavors of Linux, and read as much as you can about it. There's no way you can learn it over night; and there's no reason you - the average person - cannot learn it. The Big Secret that proprietary software monopolies don't want you to know is that computers are actually very simple. All they are made from is circuits with electricity going through them, set up in logic gates. The software is just what we run through the circuits to try to make them do something useful.

This is the new way that we, the free people, can handle our technology. And whether by GNU, Linux, BSD, Solaris, or tomorrow's Next Big Thing, it will be the way of the future.

Ω: As a couple of comments have pointed out, the age-limit thing is an arbitrary guess on my part. I say it's likely, but it isn't always true. Grade-school-aged children, for instance, also have zero trouble picking up Linux. My kids have Linux at home and get exposed to Microsoft and Apple at school. To them, they're all just different computer systems, nothing more, nothing less.

I'm still groping with the root causes. The generation thing is just the closest thing to a pattern I've seen.

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

Tweakin' your Bash Prompt

Date/Time Permalink: 01/03/07 11:00:25 am
Category: HOWTOs and Guides

About a month after moving into my new Slackware install, I have finally gotten around to setting up my cool Bash prompt again... only this time it's perfect.

Pre-requisite reading: Bash Prompt HOWTO For those of you who have never explored the deep hacking that is possible from the simple world of the $PS1 variable, and are still cruising around your terminal with a blah default prompt like:

you%yourbox ~%>

the Bash Prompt HOWTO is the ultimate geek-out on the subject. It's a shame that the link to the BashPrompt package described in the guide doesn't seem to be up.

Now for my own custom hack:
In my prompt I like to see:

  • the date
  • the time
  • the full directory path
  • the exit status of the last command

the exit status thing is for installing packages, compiling source, and other bothersome situations where I'd need to type "echo $?" to find out (clearly) if what I just tried to do worked or not.

So far with all that, I'd have:

PS1=
"{\d | \T -> \w ...\$?}"

which looks like:

prompt example 1

...with some delimiters thrown in. Now, you can see that one problem is that my prompt will expand with the directory depth, pushing what I type to word-wrap before its time. So I include a \n to escape to a newline and a crazy, unique character to mark my place:

PS1=
"{\d | \T -> \w ...\$?}\nß "

The German sz-lig character always looked to me like an elegant letter "B" for "Bash". I get that by typing ALT-223 at the console, by the way. That leaves me here:

prompt example 2

Now, one more annoyance is that when scrolling back through screens of output, my prompt tends to get lost in a sea of text. A popular solution is to change the color of the prompt using ANSI escape sequences. The Bash-Prompt HOWTO gives many elegant examples of this, but here's my simple version:

PS1=
"{\[\033[1;33m\]\d | \T -> \w ...\$?\[\033[0m\]}\nß "

That gives me a bright yellow color like this:

prompt example 3

Now for the improvement since my last exercise in prompt-hacking: I've always wanted to make the prompt dynamically change color to red when I am in root login, even when I use su to hop back and forth... from either direction! I finally figured this out from some advice in the HOWTO, where you can make up a shell script to do some function, then include a call to the script in your prompt. The escape sequence for high-red is 1;31, so I dropped the following in my /bin folder:

#!/bin/bash

if [ "$UID" -eq "0" ]; then
echo 31
fi
if [ "$UID" -eq "500" ]; then
echo 33
fi

under the name of "user_color". Now for the final tweak: I put my prompt thusly:

PS1=
"{\[\033[1;\$(user_color)m\]\d | \T -> \w ...\$?\[\033[0m\]}\nß "

I save this string in ".bash_profile" for each login that I want it to apply to, and I'm ready to rumble:

prompt example 4

and that, ladies and gentlemen, was your hack-o-the-day. Because HOOKED ON PHONICS WORKED FOR MEEEEE!

EDIT: Through further testing, I have discovered that executing the color change function misleads the output $? function. So I moved the last-command value to the front of the prompt, before the color change. It now reads:

PS1=
"{..\$?..\[\033[1;\$(user_color)m\]\d | \T -> \w \[\033[0m\]}\nß "

UPDATE Several systems later, here's what it looks like as of 2013:

Still pretty much the same, except that I've expanded the 'user_color' function to turn purple when I'm logged into another machine via SSH.

Follow me on Twitter for an update every time this blog gets a post.
Stumble it Reddit this share on Facebook

<< Previous Page :: Next Page >>
suddenly the moon