I hate backslashes. They make code harder to read.
In these four code snippets, I like the first two, but not the last two:
sleep 10 & date
sleep 10 & date
sleep 10 & \ date
sleep 10 \ & date
So? So, for the same reason, I would re-write:
grep :0: /etc/passwd | \ wc -l
as
grep :0: /etc/passwd | wc -l
and
grep -c jsh /etc/passwd \ || echo jsh not found
as
grep jsh /etc/passwd || echo jsh not found
The symbols ', ", `, &, |, &&, and ||, at the ends of lines, say "I'm not done," and automatically continue to the next line (or, in the case of the quote, until the closing quote).
For shell symbols with parens, like $( and <(, the continuation is until the matching, closing paren.
I still see people use echo. Heck, I still use echo.
But POSIX shells have had printf as a built-in for twenty years. The syntax is like C's printf().
You don't always need fancy formatting, so echo's still good for simple strings, like this:
echo 'What are you -- nuts?'
but there's no reason to use echo -n when you can use printf. None.
Just the reverse. Experiments like this:
time for i in {1..10000}; do printf $i; done > /dev/null time for i in {1..10000}; do echo -n $i; done > /dev/null
will show you that printf is about 10% faster.
Similarly, you can discard echo -e "foo\tbar" for printf "foo\tbar\n" . Why keep a bunch of flags to echo in your head if you're comfy with printf from other languages?
You can make truncating a file harder than it needs to be.
I'm walking through Hal Pomeranz's older Command-Line Kung Fu postings, both because I know there'll be useful stuff and because he has some fun challenges.
His Episode #19 attacks zeroing out an existing file. The solutions suggested are
cat /dev/null > my_file
and
cp /dev/null my_file
(which is both shorter and works even if noclobber is set, to prevent accidentally overwriting pre-existing files with > ).
Both of these are more typing than necessary. This works just as well:
> my_file
and never even invokes a command. It's all done by the shell.
What's that? You're running with set -o noclobber ?
>| my_file
If you want to do it in fewer characters, you can omit the space. :-)
My favorite programming language is still the shell.
Hal Pomeranz, whom I finally met at the OS Bridge conference in Portland last week, has a blog called Command-line Kung Fu full of shell tricks and tips. He posts to it on Tuesdays.
In today's, a post on how to decide what tools to use and when, he recommends cut(1) for some tasks because "cut is the only tool that allows you to easily pull out ranges of characters."
grep -l spammer@example.com qf* | while read i; do echo ${i:2}; done | ...
I confess I'd do it differently, but that's because I like substitution better than cuts.
for f in $(grep -l spammer@example.com qf*); do rm $f ${f/q/d}; done
It's pronounced "Tim-toady." Hal emailed me saying he still likes his way better. YMMV.
For jobs like this, where I'm using a program to write commands on-the-fly, I usually play it safe. I start off using echo to see what the shell thinks I want to do
for f in $(grep -l spammer@example.com qf*); do echo rm $f ${f/q/d}; done
which spits out a list of the generated commands.
rm qf137965 df137965 rm qf200920 df200920 ...
Then, when I think it's right, instead of removing the echo -- which risks a typo -- I recall the command, and tack on a pipe to a subshell, which executes the commands.
for f in $(grep -l spammer@example.com qf*); do echo rm $f ${f/q/d}; done |bash
I tried Twitter a while back and couldn't get excited about it. I didn't know why I'd use it, or how.
I just got back from Open Source Bridge 2009, in Portland, OR, where it was all the rage. (The other things most attendees were into were Ruby and git.)
"Okay," I said, "let me find someone who gets it, and I'll just ask how to approach it."
Ms. Amye was willing to be my evangelista, so I logged in, set up my account, and am now following a few folks that I met at the conferences (#osb09 is the Twitter "hash code"). I've even tweeted.
This weekend, I put my first videos up on YouTube. Here's why.
Three Saturdays ago, May 30, Kristina and I were in King Soopers when my cell rang. It was Kristine Smock, a mandolin player from Lyons.
There's a swarm of bees in the alley behind my house. Do you want them?
We hurried home. Kristina grabbed a cardboard filing box, shoved in a frame with old comb, tossed it in the car, and we drove out to Lyons. After she'd gotten the swarm in the box, she put on the lid and duct-taped both handles shut. Once home, she put it on the deck, pulled off one piece of tape and -- presto! -- one new hive.
I'd gotten her an observation hive for Christmas, which was still unpopulated. By last Wednesday, it was set to go and she'd drilled a hole in the wall.
A flip videorecorder was waiting for me on the porch from Amazon, so its maiden voyage was taking a video of the installation.
Okay, I had it captured. My first, little, 15' home movie. Now what? It'd be nice, for example, to show it to Kristina's parents.
Can't mail it, it's half a gig. YouTube? Uh-oh. YouTube has a 10' limit. Other services? Turns out there's a reason YouTube is popular -- they're slow and hard to use.
By the next night, I could get someone at the BLUG meeting to show me enough rudimentary Kino to chop my video and post the pieces to YouTube.
The trickiest part was figuring out to download the jmpegtools package, so that Kino would export the files in a format that YouTube liked. Figuring it out required actually reading the error messages on the screen, which told me to install the jmpegtools package. Duh.
Kevin Fenzi said I should send my shell-level realpath off to the maintainer of an appropriate package -- coreutils, maybe -- for possible inclusion.
So, I wrote unit tests, a simple Makefile and documentation: man page, README, INSTALL, stuff like that.
Kevin, wiser than I, looked and found documentation that suggested readlink -f would do the trick. And it does. I could prove it to myself because I had unit tests.
One difference in functionality, which I can live with: if the file is missing, readlink -f succeeds and reports it's in the current directory.
So, to find the path to an executable, this does the trick:
Scott Mann posted a note to the Boulder Linux Users' Group Mailing list, asking for advice about iPods, MP3 players, and what software to use to manage them under Linux.
As you'd expect, much of the advice was hyperbolic. "Don't get an iPod. They're unuseable." Quick, someone tell Steve Jobs.
I replied with my recent experience.
A few months ago, I switched my girlfriend, Kristina, over to Linux; her old, G3, iBook was finally biting the dust. She's been completely happy with Ubuntu.
Last week, she bought an iPod Nano on eBay.
She's going to fill it with
her Dad's favorite music and give it to him.
When it arrived, she took it out of the box, turned to me, and said, "How do I put music on this?"
I took Scott Mann's advice and installed Banshee. It mostly just worked. It rips CDs to ogg by default, but I kept throwing gstreamer packages at it until it said it knew how to create mp3s, too.
To my mild surprise, it now also converts flac, ogg, wmv, and wv files to mp3s, on the fly, when I drag them onto the iPod. I found this out by accident. I mean, uh, by carefully reading all the documentation.
Still, after reviewing this thread, I started to wonder whether, instead, I should have traded Kristina in for a smarter girlfriend -- one who'd have bought an mp3 player with a much better interface and then re-flashed it with Linux or RockBox herself.
When I asked her if she thought so, too, she ignored the question.
There's no standard command that gives you the absolute path to a file. That's insane. Here's an implementation.
Yes, it resolves symlinks and works on directories, too.
I couldn't figure out how to get Blogger to stop re-formatting my code, so I passed it through this, web-based, C#-formatting tool (!), and now it seems to look okay.
Argh.
// realpath - what's the real path to a file? // Turn relative paths into absolute paths, // resolve '.' and '..', // follow symlinks