Skip navigation

shell tricks

A shell function can be treated just like a ‘command’ — you can pipe input to it and stuff. I don’t know why it took me so long to figure it out. Here is a nice example:

errfmt() {
  awk '{ printf "  %68s  %s", $0, ".:!!:." }'
}

echo "please specify at least one file" | errfmt >&2

Guess what it does…

Advertisements

2 Comments

  1. Dino
    Posted October 18, 2007 at 13:49:47 UTC | Permalink

    I didn’t exactly know that either, about functions in sh scripts.

    But ya, shell scripting is impressively powerful. Many people poo-poo shells and shell scripting as something sub-human. But the truth is it’s an elegant system that was deliberately designed to do heavy work.

    I’ve thought about pipes like this..

    Take the Haskell function composition function:

    (.) :: (b -> c) -> (a -> b) -> a -> c

    Imagine we could get the Haskell-like type of lowly shell piping:

    (|) :: (a -> b) -> (b -> c) -> a -> c

    It’s like (flip (.)), backwards function composition.

  2. Posted October 18, 2007 at 17:37:33 UTC | Permalink

    More generally, typing shell commands is an interesting challenge. The first element of the a shell command is definitely and ‘arrow type’, usually taking its inputs to a stream. But the inputs themselves could be filenames or literal tokens — or ‘streams’, like stdout.

    In functional programming, we build our programs with functions; and in object-oriented programming, we build them with objects. What do we make shell programs with? Files. The shell has “first class files”. It’s an execution context where function look up can default to looking for a file and feeding it to the kernel. Shell functions tend to have a type of (Stream Bytes) -> (Stream Bytes), whether they have side effects or not. While deepening the type system of shell programs would be easy in Haskell, emulating ‘first class files’ would be hard — maybe impossible?


Post a Comment

You must be logged in to post a comment.
%d bloggers like this: