A lot of people I know seem to glory in their ignorance of the terminal.
Which would be fine if they didn’t use it every day. Yes, bash
is
ugly. On the other hand, like many ugly things, it can be used as a
brute tool to do a lot of mundane tasks.
Rather than making up some examples, here’s some of my recent shell history to illustrate this.
bash
for-loops
The basic syntax is for i in X; do (some commands) "$i" ; done
. i
is
the name of the loop variable, X
is a whitespace-separated string
which will be split into substrings according to that whitespace, and
the do
and done
mark the beginning and end of the loop.
I dunno why, but the do
cannot be its own command separated by
semicolons, unlike the done
. The semicolons are the same as in C
and
Java: they act as newlines.
The intermediate step is the interesting bit. But let’s get to the examples.
Examples From My Shell History
for i in {a..z};do
html2text http://www.berkeley.edu/academics/dept/$i.shtml > $i.md
done
The {a..z}
loops over letters in the obvious way. It works for numbers
too.
I wanted to convert a bunch of html to Markdown. I used html2text
to
download and convert each one, and a for-loop to move them to the right
spot. Since there was no whitespace in i
’s values, I didn’t bother
quoting $i
.
for i in $(find . -name '*.md'); do echo $i; done
$(..)
returns the output of the command inside as a string, which is
then fed into the for-loop.
This recursively descends into the current directory, gets a list of all Markdown files, and prints out their names. I just wanted to read the names for some reason.
for i in {1..10}; do je $i;done
This creates journal files for the last 10 days. je
is a function I
wrote to create the file.
for i in ~/.{boto,irb,latexmk,msmtp,pry,gnuplot,goobook,ctags,xsh,node,es,calc,joe,mbsync,mime,less}; do mv ~/."$i" ~/.config/ ;done
The long comma-separated list between curly braces will expand into a bunch of strings with one element of the list in each one. I don’t recall if it’s a feature of the interactive shell or if it also works in shell scripts.
I started using ~/.config
to store all my config files, and I used
this long command to move all the directories into it. Easy cleanup.
for i in *; do echo $i;done
for i in *; do rm $i;done
The first command is a glob that prints out everything in the current directory. It can fail if the directory has a lot of files in it, since globs only expand to a few thousand elements. The second command deletes all of them. I used the first as a sanity check.
for i in $(seq 1 30); do echo $i;ssh -o ConnectTimeout=2 alok@192.168.1.$i; done
I needed to log in to a home computer I use for ML, but I didn’t want to
hook it up to a monitor and get its up address. I also didn’t know about
nmap
or anything at the time. So I brute-forced it, and it worked
after about 10 iterations.
for i in $(seq 1 5); do /usr/bin/time zsh -i -c exit; done
This was the poor man’s profiling of my shell startup time.
for i in *.py;do echo test_$i;done
for i in *.py;do touch test_$i;done
This created files for all my unit tests for a Python project.