zsh: More Word Expansion
As I was mentioned in last week's tip, Zsh can expand the !
character into an event designator, substituting a previous command
into your current command… but that wasn't the tip.
The tip was that you could take part of a previous command (called a
/word designator/) instead of the entire command.
In this week's tip, I mention that these word designators can
themselves take a modifier for even more wacky hijinx.
Dirnames, Basenames and Extensions
Let's suppose that instead of getting the entire path of a previous
argument, we just wanted the directory, or the filename or just the
extension. Just out these examples:
$ cp src/reasoned_schemer/chapter4.clj ../../org/clojure/logic_002.clj
$ ls !cp:2:h ## HEAD --> Expand to:
$ ls ../../org/clojure
$ touch !cp:2:t ## TAIL --> Expand to:
$ touch logic_002.clj
$ echo "!cp:1:e" ## EXT --> Expand to:
$ echo "clj"
$ echo !cp:1:r ## ROOT --> Expand to:
$ echo src/reasoned_schemer/chapter4
Why yes, these do work inside double quotes (but not single quotes).
The modifiers are also cumulative, like:
$ echo !cp:1:h:r ## HEAD+ROOT --> Expand to:
$ echo chapter4
$ ls !cp:2:h:a ## HEAD+ABS --> Expand to:
$ ls /Users/howard/Dropbox/org/clojure
What is the :a
modifier? Read on…
Getting the Absolute Path
The :a
modifier takes the file path and converts it to an absolute path,
expanding relative ".." paths in the process. As you can expect, it doesn't
take into consideration any directory changes, as in:
$ cp src/reasoned_schemer/chapter4.clj ../../org/clojure/logic_002.clj
$ cd ..
$ ls !cp:2:a ## ABS --> Expand to:
$ ls /Users/habrams/org/clojure/logic_002.clj
ls: cannot access /Users/howard/org/clojure/logic_002.clj: No such file or directory
The :A
modifier attempts to resolve symbolic links.
What did I just run?
You can use the :c
modifier to get the file path to the command
that you ran. Why is that important? Probably helpful when something
goes wrong, for instance, let's suppose I ran this cp
command, and
I didn't want the Extended Attributes (EAs) or resource forks on my
Mac system:
$ cp -X nothing.clj /tmp
cp: invalid option -- 'X'
What is going on with my Mac!? I try to diagnose what I
previously did:
$ !cp:0:c ## CMD --> Expand to:
$ /opt/local/bin/gcp
Oh! I'm not using the cp
command that came with my system, but
picked up a GNU library version… that explains the difference.
That wasn't too much of a contrived example, was it?
Now we're getting ridiculous
The :s
modifier is a regular expression conversion… which is
either overkill or freakin' crazy (depending on who you ask):
$ ls !cp:2:s/clojure/scheme/ ## --> Expand to:
$ ls ../../org/scheme/logic_002.clj
Quote that
I assume that if you have typed in a command before, you can just
take the parameters as is in subsequent calls, however, you can
add single quotes or remove them:
$ echo '$PATH'
$PATH
$ echo !!:1:Q ## UNQUOTE --> Expand to:
$ echo $PATH
/Users/habrams/bin:/web/tools/bin:/opt/local/bin:…
$ echo !!:1:q ## QUOTE --> Expand to:
$ echo '$PATH'
$PATH
Summary
Zsh offers other modifiers, like :l
(for lowercasing the parameter)
and :u
(for uppercasing it), but these seem pretty straight-forward.
The :s
can be quite complex, so be careful. Next week, I think I'll
dive into process subsitution, but we'll see if I get distracted
when I go to Clojure/West.
Tell others about this article: