<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tim's blog (Posts about cli)</title><link>https://blog.thechases.com</link><description></description><atom:link href="https://blog.thechases.com/categories/cli.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><copyright>Contents © 2026 &lt;a href="mailto:blog@tim.thechases.com"&gt;Tim Chase&lt;/a&gt; </copyright><lastBuildDate>Sun, 31 May 2026 22:46:53 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Assorted less(1) tips</title><link>https://blog.thechases.com/posts/assorted-less-tips/</link><dc:creator>Tim Chase</dc:creator><description>&lt;aside&gt;
"word to your moms,
I came to drop bombs,
I've got more
&lt;code&gt;less&lt;/code&gt;
tips
than the Bible's got Psalms."
&lt;/aside&gt;

&lt;p&gt;
In
&lt;a href="https://www.reddit.com/r/commandline/comments/1oteeaj/whats_the_most_useful_commandline_trick_you/no5xkx4/"&gt;a
recent discussion on Reddit&lt;/a&gt;
I shared a number of tips
about the common utility
&lt;a href="https://man.openbsd.org/less.1"&gt;&lt;code&gt;less(1)&lt;/code&gt;&lt;/a&gt;
that others found helpful
so I figured I'd aggregate some of those tips here.
&lt;/p&gt;

&lt;h3 id="multiple-files"&gt;Operating on multiple files&lt;/h3&gt;

&lt;p&gt;
While most folks invoke
&lt;code&gt;less&lt;/code&gt;
at the tail of a pipeline like
&lt;figure&gt;
&lt;pre&gt;
&lt;label&gt;$ &lt;/label&gt; &lt;var&gt;command&lt;/var&gt; | less
&lt;/pre&gt;
&lt;figcaption&gt;Invoking &lt;code&gt;less&lt;/code&gt; in a pipeline&lt;/figcaption&gt;
&lt;/figure&gt;

you can directly provide one or more files to open

&lt;figure&gt;
&lt;pre&gt;
&lt;label&gt;$ &lt;/label&gt; less &lt;var&gt;README.txt file.c *.md&lt;/var&gt;
&lt;/pre&gt;
&lt;figcaption&gt;Invoking &lt;code&gt;less&lt;/code&gt; directly&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;/p&gt;

&lt;h3 id="adding-files"&gt;Adding files after starting&lt;/h3&gt;

&lt;p&gt;
When reading a document,
sometimes you want to view another file,
adding it to the file list.
Perhaps while reading some C source code
you want to also look over the corresponding header-file.
You can add that header-file to the argument list with
&lt;code&gt;:e file.h&lt;/code&gt;
&lt;/p&gt;

&lt;h3 id="navigating-multiple"&gt;Navigating multiple files&lt;/h3&gt;

&lt;p&gt;
You can navigate between multiple files using
&lt;code&gt;:n&lt;/code&gt;
to go to the next file in the argument-list, and
&lt;code&gt;:p&lt;/code&gt;
for the previous file.
You can also use
&lt;code&gt;:x&lt;/code&gt;
to rewind to the first file in the argument-list
similar to how
&lt;code&gt;:rewind&lt;/code&gt;
behaves in
&lt;code&gt;vi&lt;/code&gt;/&lt;code&gt;vim&lt;/code&gt;.
&lt;/p&gt;

&lt;h3 id="removing-files"&gt;Removing files after starting&lt;/h3&gt;

&lt;p&gt;
While I rarely feel the need to,
if you have finished with a file
and want to keep your argument list clean,
you can use
&lt;code&gt;:d&lt;/code&gt;
to delete the current file from the argument-list.
&lt;/p&gt;

&lt;h2 id="navigating-within"&gt;Navigating&lt;/h2&gt;

&lt;h3 id="jump-to-line"&gt;Jumping to a particular line-number&lt;/h3&gt;

&lt;p&gt;
Use
&lt;code&gt;&lt;var&gt;«count»&lt;/var&gt;G&lt;/code&gt;
to jump to a particular line-number.
So using
&lt;code&gt;&lt;var&gt;3141&lt;/var&gt;G&lt;/code&gt;
will jump to line &lt;var&gt;3141&lt;/var&gt;.
It helps to display
&lt;a href="https://blog.thechases.com/posts/assorted-less-tips/#option-N"&gt;line numbers&lt;/a&gt;.
&lt;/p&gt;

&lt;h3 id="jump-to-percent"&gt;Jumping to a particular percentage-offset&lt;/h3&gt;

&lt;p&gt;
Similarly, using
&lt;code&gt;&lt;var&gt;«count»&lt;/var&gt;%&lt;/code&gt;
jumps to that percentage-offset of the file.
So if you want to go to ¾
of the way through the file, you can type
&lt;code&gt;75%&lt;/code&gt;
to jump right there.
&lt;/p&gt;

&lt;h3 id="searching"&gt;Searching&lt;/h3&gt;

&lt;p&gt;
While many folks know you can search forward with
&lt;code&gt;/&lt;var&gt;«pattern»&lt;/var&gt;&lt;/code&gt;
and some people know you can use
&lt;code&gt;?&lt;var&gt;«pattern»&lt;/var&gt;&lt;/code&gt;
to search backwards,
or use
&lt;code&gt;n&lt;/code&gt;/&lt;code&gt;N&lt;/code&gt;
to search again for the next/previous match,
&lt;code&gt;less&lt;/code&gt;
provides modifiers you can specify
before the pattern to modify its behavior:
&lt;/p&gt;

&lt;dl id="search-modifier"&gt;
 &lt;dt&gt;&lt;code&gt;!&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;
  Find the next line that
  &lt;strong&gt;doesn't&lt;/strong&gt;
  match the pattern
 &lt;/dd&gt;
 &lt;dt&gt;&lt;code&gt;*&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;
 search across multiple files,
 starting from the current location
 in the current file
 &lt;/dd&gt;
 &lt;dt&gt;&lt;code&gt;@&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;
 rewind to the first file
 and search from there
 &lt;/dd&gt;
 &lt;dt&gt;&lt;code&gt;@*&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;
 rewind to the first file
 and search from there
 across multiple files
 &lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;
Thus you would use
&lt;code&gt;/@*&lt;var&gt;«pattern»&lt;/var&gt;&lt;/code&gt;
to search for "pattern"
starting with the first file.
&lt;/p&gt;

&lt;h2 id="filtering"&gt;Filtering lines&lt;/h2&gt;

&lt;p&gt;
Using
&lt;code&gt;&amp;amp;&lt;/code&gt;
lets you specify a pattern
and filter the displayed lines
to only those matching the pattern,
much like an internal
&lt;code&gt;grep&lt;/code&gt;
command.
If you modify it with
&lt;code&gt;!&lt;/code&gt;,
so it will display only those lines that do
&lt;em&gt;not match&lt;/em&gt;
the pattern, like
&lt;code&gt;&amp;amp;!&lt;var&gt;«pattern»&lt;/var&gt;&lt;/code&gt;.
I find this particularly helpful for browsing log-files.
&lt;/p&gt;

&lt;h2 id="bookmarking"&gt;Bookmarking&lt;/h2&gt;
&lt;p&gt;
You can bookmark points in a file with
&lt;code&gt;m&lt;/code&gt;
followed by a letter,
then jump back to that bookmark with
&lt;code&gt;'&lt;/code&gt;
followed by the same letter.
These apply globally across all open files,
so if you
&lt;code&gt;ma&lt;/code&gt;
in the third file,
then navigate away to other files,
using
&lt;code&gt;'a&lt;/code&gt;
will take you back to the marked location
in that third file.
I use marks most when reading man-pages,
dropping one mark at the
&lt;tt&gt;OPTIONS&lt;/tt&gt;
section such as
&lt;code&gt;mo&lt;/code&gt;,
and another at the
&lt;tt&gt;EXAMPLES&lt;/tt&gt;
section,
such as
&lt;code&gt;me&lt;/code&gt;,
then bounce back and forth between them with
&lt;code&gt;'o&lt;/code&gt;
and
&lt;code&gt;'e&lt;/code&gt;.
While you can use any of
the 26 lowercase or uppercase letters
(for a total of 52 marks),
I rarely use more than two or three
either in alphabetical order
("a", "b", "c"),
or assigning mnemonics like in the
&lt;code&gt;man&lt;/code&gt;-page example above.
&lt;/p&gt;

&lt;h3 id="bracket-matching"&gt;Bracket matching&lt;/h3&gt;

&lt;p&gt;
If the first line on the screen contains a
&lt;code&gt;(&lt;/code&gt;,
&lt;code&gt;[&lt;/code&gt;,
or
&lt;code&gt;{&lt;/code&gt;,
typing that character
will jump to the matching/closing character,
putting it on the bottom line of the screen.
Similarly, if a closing
&lt;code&gt;)&lt;/code&gt;,
&lt;code&gt;]&lt;/code&gt;,
or
&lt;code&gt;}&lt;/code&gt;,
character appears on the last line,
typing that closing character
will jump to the matching/opening character,
putting it at the top of the screen.
I find it a little disorienting
if they fall &lt;code&gt;less&lt;/code&gt; than a screen-height apart
because what feels like a forward motion
to find the next matching close-bracket
might actually result in shifting the screen
&lt;em&gt;down&lt;/em&gt;
rather than
&lt;em&gt;up&lt;/em&gt;
which feels backwards.
&lt;/p&gt;

&lt;p&gt;
While I don't use it much,
you can also specify match-pairs using
&lt;code&gt;&lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;ctrl+f&lt;/kbd&gt;&lt;/code&gt;
or
&lt;code&gt;&lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;ctrl+b&lt;/kbd&gt;&lt;/code&gt;
followed by the opening/closing pair of characters
such as
&lt;code&gt;&lt;kbd&gt;alt&lt;/kbd&gt;+&lt;kbd&gt;ctrl+f&amp;lt;&amp;gt;&lt;/kbd&gt;&lt;/code&gt;
to define a "&amp;lt;"…"&amp;gt;" pair
and jump between them
in a manner similar to the
&lt;code&gt;(&lt;/code&gt;/&lt;code&gt;)&lt;/code&gt;,
&lt;code&gt;[&lt;/code&gt;/&lt;code&gt;]&lt;/code&gt;,
and
&lt;code&gt;{&lt;/code&gt;/&lt;code&gt;)&lt;/code&gt;
motions.
&lt;/p&gt;

&lt;h2 id="toggling-options"&gt;Toggling options without restarting&lt;/h2&gt;

&lt;p&gt;
While the
&lt;code&gt;man&lt;/code&gt;-page
documents many flags you can pass
on the command-line,
you can also toggle boolean options from inside
&lt;code&gt;less&lt;/code&gt;.
I find this particularly helpful
when I've fed the output of a long-running process to
&lt;code&gt;less&lt;/code&gt;
and don't want to re-run it
because it will take a long time.
Instead of quitting,
you can type a literal
&lt;code&gt;-&lt;/code&gt;
followed by the option you want to change.
I most commonly want to toggle word-wrap for long lines,
so instead of quitting and adding
&lt;code&gt;-S&lt;/code&gt;
at the end of my pipeline,
I can type
&lt;code&gt;-S&lt;/code&gt;
directly in
&lt;code&gt;less&lt;/code&gt;.
Options I commonly toggle:
&lt;/p&gt;&lt;dl id="options"&gt;
 &lt;dt id="option-S"&gt;&lt;code&gt;-S&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;word-wrap (mnemonic "splitting long lines")&lt;/dd&gt;
 &lt;dt id="option-G"&gt;&lt;code&gt;-G&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;search-highlighting&lt;/dd&gt;
 &lt;dt id="option-I"&gt;&lt;code&gt;-i&lt;/code&gt;/&lt;code&gt;-I&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;smart-case/case-sensitivity for searches&lt;/dd&gt;
 &lt;dt id="option-R"&gt;&lt;code&gt;-R&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;ANSI-color escaping&lt;/dd&gt;
 &lt;dt id="option-N"&gt;&lt;code&gt;-N&lt;/code&gt;/&lt;code&gt;-n&lt;/code&gt;&lt;/dt&gt;
 &lt;dd&gt;show/hide line-numbers&lt;/dd&gt;
&lt;/dl&gt;


&lt;h2 id="external-commands"&gt;Running external commands&lt;/h2&gt;

&lt;p&gt;
The
&lt;code&gt;!&lt;/code&gt;
lets you invoke an external command.
I don't do this often,
but occasionally I want some simple reference
like the current date
(&lt;code&gt;!date&lt;/code&gt;)
or to do some simple math
(&lt;code&gt;!bc&lt;/code&gt;).
&lt;/p&gt;

&lt;h2 id="env-vars"&gt;Default options with &lt;code&gt;$LESS&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;
You might find yourself regularly setting
a common group of
&lt;a href="https://blog.thechases.com/posts/assorted-less-tips/#options"&gt;options&lt;/a&gt;
so you can put those in your environment
(usually in your shell startup file like
&lt;code&gt;~/.bashrc&lt;/code&gt;)
like
&lt;code&gt;LESS="-RNe"&lt;/code&gt;
if you want to
&lt;a href="https://blog.thechases.com/posts/assorted-less-tips/#option-R"&gt;show ANSI colors&lt;/a&gt;,
&lt;a href="https://blog.thechases.com/posts/assorted-less-tips/#option-N"&gt;show line-numbers&lt;/a&gt;,
and exit automatically when you reach the end of the file.
&lt;/p&gt;

&lt;h2 id="other-misc"&gt;Other misc&lt;/h2&gt;

&lt;p&gt;
&lt;code&gt;less&lt;/code&gt;
has a few other corners that I've never really used,
but figured I'd document here:
&lt;/p&gt;

&lt;h3 id="tags"&gt;Tags&lt;/h3&gt;

&lt;p&gt;
While I've used tags in
&lt;code&gt;vi&lt;/code&gt;/&lt;code&gt;vim&lt;/code&gt;
to easily jump between definitions.
However, even though
&lt;code&gt;less&lt;/code&gt;
provides support for tags generated by
&lt;code&gt;ctags&lt;/code&gt;.
I've never found cause to use them.
&lt;/p&gt;

&lt;h3 id="external-editor"&gt;Editing the current document&lt;/h3&gt;

&lt;p&gt;
The
&lt;code&gt;v&lt;/code&gt;
command will open your
&lt;code&gt;$VISUAL&lt;/code&gt;
editor on the current document.
&lt;/p&gt;

&lt;h3 id="log-output"&gt;"Log" output&lt;/h3&gt;

&lt;p&gt;
&lt;code&gt;less&lt;/code&gt;
lets you redirect the output
it has gathered from
&lt;abbr title="standard input"&gt;stdin&lt;/abbr&gt;
to a file using the
&lt;code&gt;o&lt;/code&gt;
command
(or the
&lt;code&gt;O&lt;/code&gt;
command to overwrite an existing file).
This might come in handy because
&lt;code&gt;less&lt;/code&gt;
won't let you
&lt;a href="https://blog.thechases.com/posts/assorted-less-tips/#external-editor"&gt;edit stdin
in an external editor&lt;/a&gt;
but you can write it directly to a file.
&lt;/p&gt;</description><category>cli</category><category>console</category><category>less</category><guid>https://blog.thechases.com/posts/assorted-less-tips/</guid><pubDate>Tue, 11 Nov 2025 15:28:50 GMT</pubDate></item><item><title>Unsorted ed(1) Tips and Tricks</title><link>https://blog.thechases.com/posts/cli/unsorted-ed-tips-and-tricks/</link><dc:creator>Tim Chase</dc:creator><description>&lt;h2&gt;Edit text like a pro with ed(1)&lt;/h2&gt;
&lt;p&gt;
I came across
&lt;a href="http://blog.terminal.com/vi-tips-and-tricks/"&gt;Ten
unsorted vi/vim tricks, volume one&lt;/a&gt;
&amp;amp;
&lt;a href="https://blog.terminal.com/ten-unsorted-vi-vim-tricks-volume-2/"&gt;Ten
unsorted vi/vim tricks, volume two&lt;/a&gt;
&lt;aside&gt;
Note: these seem to have vanished from the web
so the point-for-point response-style of this post
feels a bit weird now.
This also means that I can't revisit those
articles to finish writing this one,
so this post is pretty much abandoned/unfinished.
&lt;/aside&gt;
and thought I'd compile a similar list for
&lt;code&gt;ed(1)&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
In this post I will present counterpoints with easy &amp;amp;
but useful tricks using
&lt;code&gt;ed(1)&lt;/code&gt;
commands and, in the Unix philosophy, external tools.
&lt;/p&gt;

&lt;p&gt;
You might ask, &lt;a href="https://blog.thechases.com/posts/cli/why-ed1/"&gt;&lt;strong&gt;why
&lt;code&gt;ed(1)&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;?

&lt;/p&gt;

&lt;dl&gt;
 &lt;dt&gt;&lt;code&gt;ed(1)&lt;/code&gt; is always&lt;sup&gt;*&lt;/sup&gt; there&lt;/dt&gt;
 &lt;dd&gt;
  Since
  &lt;code&gt;ed(1)&lt;/code&gt;
  is required by POSIX,
  you
  &lt;em&gt;should&lt;/em&gt;
  find it in any *nix/Linux distribution.
  Sadly, many distros drop
  &lt;code&gt;ed(1)&lt;/code&gt;
  from their core installations,
  making it an optional add-on package.
 &lt;/dd&gt;

 &lt;dt&gt;&lt;code&gt;ed(1)&lt;/code&gt; is small but mighty&lt;/dt&gt;
 &lt;dd&gt;
 On various systems at my disposal,
 &lt;code&gt;ed(1)&lt;/code&gt;
 clocks in at between 51k and 183k,
 while
 &lt;code&gt;nano&lt;/code&gt;
 is 2-4x as large,
 &lt;code&gt;vi/vim&lt;/code&gt;
 is 3-20x as large, and
 &lt;code&gt;emacs&lt;/code&gt;
 lumbers in at over
 &lt;span title="Insert standard joke about Eight Megabytes And Continually Swapping"&gt;8 megs&lt;/span&gt;.
 Yet
 &lt;code&gt;ed(1)&lt;/code&gt;
 provides a lot of functionality
 in those meager few bytes.
 &lt;/dd&gt;

 &lt;dt&gt;&lt;code&gt;ed(1)&lt;/code&gt; needs no configuration&lt;/dt&gt;
 &lt;dd&gt;
 You don't have to worry
 about sitting down at a foreign machine
 and not knowing how
 &lt;code&gt;ed(1)&lt;/code&gt;
 is configured.
 Yes, there are some subtle differences
 between
 GNU &lt;code&gt;ed(1)&lt;/code&gt;
 and
 BSD &lt;code&gt;ed(1)&lt;/code&gt;
 but the vast majority is the same.
 &lt;/dd&gt;
&lt;/dl&gt;

&lt;h2&gt;Getting some help&lt;/h2&gt;
&lt;p&gt;
&lt;code&gt;ed(1)&lt;/code&gt;
is known for its terse
&lt;code&gt;?&lt;/code&gt;
reply to any issue.
You can request in-line help
with the
&lt;kbd&gt;h&lt;/kbd&gt;
command for a bit of a hint.
Additionally, the
&lt;code&gt;man&lt;/code&gt;
page should cover everything you need to know.
&lt;figure&gt;
&lt;pre&gt;
s/oof/bar/
?
h
No match
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Search and replace&lt;/h2&gt;
&lt;p&gt;
To search, use the &lt;kbd&gt;/&lt;/kbd&gt; or &lt;kbd&gt;?&lt;/kbd&gt; command
followed by your search pattern.
&lt;figure&gt;
&lt;pre&gt;
/pattern/n
18 this line contains "pattern"
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;p&gt;
To search and replace on the current line, use the
&lt;kbd&gt;s&lt;/kbd&gt; command:
&lt;figure&gt;
&lt;pre&gt;
s/foo/bar/g
&lt;/pre&gt;
&lt;/figure&gt;
or, apply the changes over a range:
&lt;figure&gt;
&lt;pre&gt;
4,18s/foo/bar/g
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Show line numbers&lt;/h2&gt;
&lt;p&gt;
To show line numbers in &lt;code&gt;ed(1)&lt;/code&gt;
add the suffix &lt;kbd&gt;n&lt;/kbd&gt; to your command, for example
&lt;figure&gt;
&lt;pre&gt;
,s/foo/bar/n
g/pattern/n
10zn
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Execute an external command from within
&lt;code&gt;ed(1)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;
Use the &lt;kbd&gt;!&lt;/kbd&gt; command to execute 
&lt;figure&gt;
&lt;pre&gt;
!ls
file.txt
!
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Insert an existing file into the current one&lt;/h2&gt;
&lt;p&gt;
In case you need to insert the contents of a file into the
one you're currently writing, use the &lt;kbd&gt;r&lt;/kbd&gt;
command.
&lt;figure&gt;
&lt;pre&gt;
r file.txt
1625
&lt;/pre&gt;
&lt;/figure&gt;
Note that &lt;code&gt;ed(1)&lt;/code&gt; lets you know how many bytes
were added to your file.
&lt;/p&gt;

&lt;h2&gt;Display changes performed since last save&lt;/h2&gt;
&lt;p&gt;
This trick uses &lt;code&gt;diff&lt;/code&gt; to display the difference
between the file on disk and the current editing buffer.
&lt;figure&gt;
&lt;pre&gt;
w !diff -u file.txt -
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Indendent and un-indenting lines&lt;/h2&gt;
&lt;p&gt;
To indent a range of lines, substitute the beginning of the
line with either spaces or tabs:
&lt;figure&gt;
&lt;pre&gt;
12,18s/^/    /
.,+4s/^/{tab}/
&lt;/pre&gt;
&lt;/figure&gt;
To unindent, strip off that number of leading indentation:
&lt;figure&gt;
&lt;pre&gt;
12,18s/^    //
12,18s/^ \{4\}//
.,+4s/^{tab}//
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Undo &amp;amp; redo&lt;/h2&gt;
&lt;p&gt;
&lt;code&gt;ed(1)&lt;/code&gt; provides one level of undo/redo, using
the &lt;kbd&gt;u&lt;/kbd&gt; command to toggle between them:
&lt;figure&gt;
&lt;pre&gt;
$ ed
1a
hello
world
.
2d
,n
1 hello
u
,n
1 hello
2 world
u
,n
1 hello
Q
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Insert the output of an external command&lt;/h2&gt;
&lt;p&gt;
Similar to the insertion of a file above,
&lt;code&gt;ed(1)&lt;/code&gt;
lets you use the
&lt;kbd&gt;r !&lt;/kbd&gt;
command to read the output 
of an external program:
&lt;figure&gt;
&lt;pre&gt;
r !ls -l
&lt;/pre&gt;
&lt;/figure&gt;
&lt;/p&gt;

&lt;h2&gt;Record commands&lt;/h2&gt;
&lt;p&gt;
(you can do this with
&lt;code&gt;rlwrap&lt;/code&gt;
but
&lt;a href="https://github.com/hanslub42/rlwrap/issues/36#issuecomment-143751189"&gt;a
bug in
&lt;code&gt;rlwrap&lt;/code&gt;
&lt;/a&gt;
caused repeated segfaults)
&lt;/p&gt;

&lt;h2&gt;Command history&lt;/h2&gt;
&lt;p&gt;
Since &lt;code&gt;ed(1)&lt;/code&gt; appends to the terminal window
rather than overwriting and redrawing the screen, the entire
editing history for the given &lt;code&gt;ed(1)&lt;/code&gt; session is
available for review.
&lt;/p&gt;</description><category>cli</category><category>ed</category><guid>https://blog.thechases.com/posts/cli/unsorted-ed-tips-and-tricks/</guid><pubDate>Sat, 06 Feb 2016 23:35:09 GMT</pubDate></item><item><title>Using ed(1) as a password manager</title><link>https://blog.thechases.com/posts/cli/using-ed1-as-a-password-manager/</link><dc:creator>Tim Chase</dc:creator><description>&lt;p&gt;
I recently came across
&lt;a href="http://invert.svbtle.com/using-vim-as-a-password-manager"&gt;a
post on using vim as a password manager&lt;/a&gt;
so I thought I'd post a companion article on using
&lt;code&gt;ed(1)&lt;/code&gt;
as a password manager.
&lt;/p&gt;

&lt;p&gt;
The main goal is to be able to keep the secrets encrypted at all
times on disk, only decrypting within the active
&lt;code&gt;ed(1)&lt;/code&gt;
session.
&lt;/p&gt;

&lt;!-- TEASER_END --&gt;

&lt;p&gt;
BSD
&lt;code&gt;ed(1)&lt;/code&gt;
offers an
&lt;kbd&gt;x&lt;/kbd&gt;
command (well,
&lt;a href="http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/bin/ed/main.c.diff?r1=1.36&amp;amp;r2=1.37"&gt;OpenBSD removed it in revision 1.37 of
&lt;code&gt;/src/bin/ed/main.c&lt;/code&gt;
"because DES"&lt;/a&gt;)
that allows for weak DES encryption of the file.  However, we
want stronger encryption and portability between various versions
of
&lt;code&gt;ed(1)&lt;/code&gt;
so will ignore this option.
&lt;/p&gt;

&lt;h2&gt;Writing our encrypted password file to disk&lt;/h2&gt;

&lt;p&gt;
To begin, we'll open up
&lt;code&gt;ed(1)&lt;/code&gt;
and add some password content
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
user@hostname$ ed
a
https://example.com
Username: demo
Password: Pa$$w0rd1

imaps://example.edu
Username: jstudent@example.edu
Password: ed(1)uc8

.
&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;
Now, instead of writing the unencrypted password file, we'll use
&lt;code&gt;gnupg&lt;/code&gt;
to encrypt the file and write it out to the disk by piping the
file through
&lt;code&gt;gpg&lt;/code&gt;
instructing it to write to our password file.
Note the trailing "&lt;kbd&gt;-&lt;/kbd&gt;" which tells
&lt;code&gt;gpg&lt;/code&gt;
to read the input from
&lt;code&gt;stdin&lt;/code&gt;.
&lt;code&gt;gpg&lt;/code&gt;
will prompt for a passphrase and confirmation of that password.
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
w !gpg --symmetric --output passwords.gpg -
Enter passphrase: Password1
Repeat passphrase: Password1
127
&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;
&lt;code&gt;ed(1)&lt;/code&gt;
informs us that it successfully piped our 127 bytes of data
through
&lt;code&gt;gpg&lt;/code&gt;
but we can confirm that the
&lt;code&gt;passwords.gpg&lt;/code&gt;
file was written and then we can quit to go about our day:
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
!ls passwords.gpg
passwords.gpg
!
q
&lt;/pre&gt;
&lt;/figure&gt;

&lt;h2&gt;Reading our encrypted password file from disk&lt;/h2&gt;

&lt;p&gt;
Now, we want to be able to look up a password to enter at some
future point.  So we fire up
&lt;code&gt;ed(1)&lt;/code&gt;
and decrypt our passwords.
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
user@hostname$ ed
r !gpg --decrypt passwords.gpg
Enter passphrase: Password1
&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;
We want to look up our log-in credentials for our email server so
we issue
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
?imap.*edu
imaps://example.edu
+
Username: jstudent@example.edu
+
Password: ed(1)uc8
Q
&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;
(Yes, using
"&lt;kbd&gt;+&lt;/kbd&gt;"
can be replaced with just hitting
"&lt;kbd&gt;&amp;lt;Enter&amp;gt;&lt;/kbd&gt;") Alternatively, we could use
&lt;code&gt;grep(1)&lt;/code&gt;
or
&lt;code&gt;sed(1)&lt;/code&gt;
to filter the results and show some context:
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
user@hostname$ gpg --decrypt passwords.gpg | grep -A2 example.com
Enter passphrase: Password1
https://example.com
Username: demo
Password: Pa$$w0rd1
user@hostname$ gpg --decrypt passwords.gpg | sed -n '/example.com/,/^$/p'
Enter passphrase: Password1
https://example.com
Username: demo
Password: Pa$$w0rd1
&lt;/pre&gt;
&lt;/figure&gt;

&lt;h2&gt;Modifying our password lists&lt;/h2&gt;

&lt;p&gt;
Now we want to modify our document and/or change our
master-password:
&lt;/p&gt;

&lt;figure&gt;
&lt;pre&gt;
user@hostname$ ed
r !gpg --decrypt passwords.gpg
Enter passphrase: Password1
127
3s/Pa..w0rd1/Pbuttwrd1
Password: Pbuttwrd1
$a
https://twitter.com/
Username: ed1conf
Password: EyeDonutThinkSew

.
w !gpg --symmetric --output passwords.gpg -
Enter passphrase: NewPassword2
Repeat passphrase: NewPassword2
File `passwords.gpg` exists. Overwrite? (y/N) y
194
&lt;/pre&gt;
&lt;/figure&gt;

&lt;p&gt;
And there you have it:  using
&lt;code&gt;ed(1)&lt;/code&gt;
as a password manager.
&lt;/p&gt;</description><category>cli</category><category>ed</category><guid>https://blog.thechases.com/posts/cli/using-ed1-as-a-password-manager/</guid><pubDate>Fri, 06 Nov 2015 21:36:29 GMT</pubDate></item><item><title>Why ed(1)?</title><link>https://blog.thechases.com/posts/cli/why-ed1/</link><dc:creator>Tim Chase</dc:creator><description>&lt;p&gt;
As the weirdo behind the somewhat tongue-in-cheek
&lt;tt&gt;@ed1conf&lt;/tt&gt;
account on
&lt;a href="https://twitter.com/ed1conf"&gt;Twitter&lt;/a&gt;
and
&lt;a href="https://bsd.network/@ed1conf"&gt;Mastodon&lt;/a&gt;,
account I'm occasionally asked "Why
&lt;code&gt;ed(1)&lt;/code&gt;?"
Hopefully some of my reasons for learning &amp;amp; using
&lt;code&gt;ed(1)&lt;/code&gt;
can pique your interest in taking the time to get to know
this little piece of history.
&lt;/p&gt;

&lt;!-- TEASER_END --&gt;

&lt;h2&gt;Ubiquity&lt;/h2&gt;
&lt;p&gt;
Sometimes your favorite
&lt;code&gt;$EDITOR&lt;/code&gt;
is installed, sometimes it's not.  Some, like
&lt;code&gt;vi&lt;/code&gt;/&lt;code&gt;vim&lt;/code&gt;
are just about everywhere.  Other times, you would have to
have sufficient privileges/space to install or compile your
editor of choice.  But if you know
&lt;code&gt;ed&lt;/code&gt;,
nearly every Linux/BSD/Mac has it installed because
&lt;a href="http://pubs.opengroup.org/onlinepubs/009604599/utilities/ed.html"&gt;it's part of the POSIX standard&lt;/a&gt;.  It's even small
enough to fit on most recovery media without breaking the
bank.  But between
&lt;code&gt;ed&lt;/code&gt;
and
&lt;code&gt;vi/vim&lt;/code&gt;,
I know that I can get things done even when I'm on a new
machine.
&lt;/p&gt;

&lt;h2&gt;Sometimes it's the only editor you have&lt;/h2&gt;
&lt;p&gt;
Several times in my life
&lt;code&gt;ed&lt;/code&gt;
has been the only editor available in certain environments.
&lt;/p&gt;&lt;ul&gt;
 &lt;li&gt;
 At
 &lt;code&gt;$DAYJOB[-1]&lt;/code&gt;
 the Linux-based router needed some configuration changes
 that the web interface didn't accommodate.  So a quick
 terminal connection later
 (&lt;code&gt;telnet&lt;/code&gt;, &lt;em&gt;sigh&lt;/em&gt;), I discovered that
 &lt;code&gt;ed&lt;/code&gt;
 was the only editor available.  No problem.  Edited the
 config file and we were back up and running with the proper
 changes.
 &lt;/li&gt;

 &lt;li&gt;
 At the same
 &lt;code&gt;$DAYJOB[-1]&lt;/code&gt;,
 I developed software for a
 &lt;a href="http://cybarcode.com/sites/cy/files/styles/xlarge_1/public/images/epson/eht-30.jpg"&gt;ruggedized hand-held device and its attached printer&lt;/a&gt;.
 This was back when
 &lt;abbr title="Personal Digital Assitants"&gt;PDA&lt;/abbr&gt;s
 were just becoming popular, so this thing was a brick.
 The DOS-based operating system had no built-in editor,
 meaning editing files usually meant laboriously copying the
 file over a serial link to the PC, editing it there, then
 sending it back down.  I longed for the ability to cut that
 time down but very few of the full-screen editors I tried
 were even able to successfully paint on the small LCD
 screen-buffer properly, and of those that did, the on-screen
 keyboard took up so much screen real-estate as to make them
 useless.  So I installed a DOS build of
 &lt;code&gt;ed&lt;/code&gt;
 and it worked like a charm (better than
 &lt;code&gt;edlin.exe&lt;/code&gt;
 that I also tried).  Editing turn-around and testing went
 from 15-20 minutes down to 3-5 minutes per iteration.
 &lt;/li&gt;

 &lt;li&gt;
 Some platforms such as
 &lt;a href="https://heroku.com/"&gt;Heroku&lt;/a&gt;
 &lt;a href="http://www.evans.io/posts/heroku-survival-guide/"&gt;
 provide only
 &lt;code&gt;ed&lt;/code&gt;
 as their editor&lt;/a&gt;.
 Not usually an issue since most of the time you're not
 trying to edit live on the server.  But if you need to do
 it, it's nice to know how.
 &lt;/li&gt;

 &lt;li&gt;
 On some &lt;abbr title="Multi-user dungeons"&gt;MUD&lt;/abbr&gt;
 games
 and old
 &lt;abbr title="Bulletin board systems"&gt;BBS&lt;/abbr&gt;es,
 the text-editor is often an
 &lt;code&gt;ed&lt;/code&gt;-like editor.
 &lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;Visible editing history&lt;/h2&gt;
&lt;p&gt;
Unless you have a key-echoing utility like
&lt;a href="http://seminar.io/projects/screenkey/"&gt;Screenkey&lt;/a&gt;
or Screenflick, it's hard for an audience to see exactly
what you did when you're editing during a presentation.
It's nice to for the audience to be able to see
&lt;em&gt;exactly&lt;/em&gt;
what you typed if they're trying to follow
along.
&lt;/p&gt;

&lt;h2&gt;All commands are ASCII text&lt;/h2&gt;
&lt;p&gt;
Sometimes your terminal emulator or keyboard isn't
configured correctly.  Function keys, arrows,
&lt;code&gt;alt-&lt;/code&gt;
and
&lt;code&gt;meta-&lt;/code&gt;modifiers
may not transmit properly.  Since all of
&lt;code&gt;ed&lt;/code&gt;'s commands are basic ASCII, it works even
if your keyboard/terminal is unable to send extended
characters properly.
&lt;/p&gt;

&lt;h2&gt;It works when &lt;code&gt;$TERM&lt;/code&gt; is messed up&lt;/h2&gt;
&lt;p&gt;
Likewise, your
&lt;code&gt;$TERM&lt;/code&gt;
setting can get messed up.  Sometimes full-screen terminal
applications leave the screen in a state where everything is
somewhat garbled.  Yes, there's
&lt;code&gt;reset&lt;/code&gt;
which will let you reset the terminal back to some sensible
defaults, but sometimes your
&lt;code&gt;termcap&lt;/code&gt;
database has trouble too.  An editor that only uses
&lt;code&gt;stdin&lt;/code&gt;
and
&lt;code&gt;stdout&lt;/code&gt;
can save your bacon.
&lt;/p&gt;

&lt;h2&gt;Accessibility&lt;/h2&gt;
&lt;p&gt;
Because
&lt;code&gt;ed&lt;/code&gt;
reads all of its commands from
&lt;code&gt;stdin&lt;/code&gt;
and writes all output to
&lt;code&gt;stdout&lt;/code&gt;
in a serial fashion, it's very usable in a screen-reader
like
&lt;a href="http://yasr.sourceforge.net/"&gt;&lt;code&gt;yasr&lt;/code&gt;&lt;/a&gt;
or
&lt;a href="http://www.linux-speakup.org/"&gt;&lt;code&gt;speakup&lt;/code&gt;&lt;/a&gt;
allowing you to edit text without a screen.  If you've never
edited text sightless, give it a try some time.
&lt;/p&gt;

&lt;h2&gt;Scriptability&lt;/h2&gt;
&lt;p&gt;
Because
&lt;code&gt;ed&lt;/code&gt;
reads all of its commands from
&lt;code&gt;stdin&lt;/code&gt;
it's easy to write a script that will edit a file in an
automated fashion.
&lt;/p&gt;

&lt;h2&gt;Previous output&lt;/h2&gt;
&lt;p&gt;
On occasion, I want to see the output of one or more
previous shell commands while I continue to edit.  A
full-screen editor takes over the entire screen, preventing
me from seeing that output.  With
&lt;code&gt;ed&lt;/code&gt;
the previous output is right there and remains in my
scroll-back buffer for reference while I edit.
I find this particularly useful when using
&lt;code&gt;\e&lt;/code&gt;
in
&lt;code&gt;psql&lt;/code&gt;
or
&lt;code&gt;mysql&lt;/code&gt;
if my
&lt;code&gt;$EDITOR&lt;/code&gt;
is set to
&lt;code&gt;ed&lt;/code&gt;.
This allows me to edit the SQL while keeping the results of
my previous query visible.
&lt;/p&gt;

&lt;h2&gt;Small, fast, light&lt;/h2&gt;
&lt;p&gt;
On resource-constrained systems, sometimes you need
something light like
&lt;code&gt;ed&lt;/code&gt;
where the executable and memory-footprint are measured in
kilobytes rather than megabytes.  This is less of a problem
on most systems these days, but with small
resource-constrained
&lt;abbr title="System On Chip"&gt;SOC&lt;/abbr&gt;
and embedded boards running Linux or BSD, a light-weight
yet powerful editor can help.
&lt;/p&gt;

&lt;h2&gt;Usable on low-bandwidth/high-latency connections&lt;/h2&gt;
&lt;p&gt;
Sometimes you are connected by a slow or very laggy
connection.  Whether this is a satellite uplink, a 300-baud
serial connection, or a congested WAN link, sometimes you
simply want to edit productively without the overhead of
repainting the screen.
&lt;/p&gt;

&lt;h2&gt;Showing off&lt;/h2&gt;
&lt;p&gt;
Finally, there's a small measure of grey-beard prestige
that comes with
&lt;a href="http://www.gnu.org/fun/jokes/ed.msg.html"&gt;using
an editor that baffles so many people&lt;/a&gt;.  It's a fast way
to demonstrate that I'm not some newbie with cert-only
knowledge, but that I enjoy Unix history and working at the
command-line.  Or maybe it shows that I'm just a little
crazy.
&lt;/p&gt;</description><category>cli</category><category>ed</category><guid>https://blog.thechases.com/posts/cli/why-ed1/</guid><pubDate>Thu, 10 Sep 2015 01:55:08 GMT</pubDate></item></channel></rss>