I find myself always having to arrow up and going backwards through the command line to change one part of an earlier command that is pipped to a later grep
or head
or whatever command.
For a crude example: searching dmesg
for a given string and only wanting the last 5 occurrences.
I would do the above such that:
dmesg | grep -i USB | tail -n 5
but then if I want to change the search term or what I am searching for or the source, I am waiting for my cursor to backtrace to the relevant part of the line. I'd like to move that to the end of the line such that the above example could be represented as (I know this is incorrect):
tail -n 5 < dmesg | grep -i USB
(and I could then search for sda
)
as I said, this is a crude example and is indicative of the sort of thing I'd LIKE to do, but not actually what I want to do, ie. this isn't about dmesg
or the use of grep
and tail
, but how to interact between these programs placing the "variable" at the end.
This could be further exampled on getting the seek time on a DNS enquiry such that:
dig google.com | grep msec
(let's move google.com
to the end so that I can then test another domain) via
grep msec < dig google.com
again, poor examples. I am talking more about when I have input/outputs flowing between multiple programs
I do admit I only have a basic understanding of piping and redirection which could be summarised as:
- piping (
|
) using thestdout
of one program to feed into thestdin
of another - redirect (
>
) taking thestdout
of one program and feeding it into a file (aside: could it be redirected elsewhere other than the only obvious ones I can think of
> /dev/null
or
> /dev/sda
or
> {said file}
whereas piping is program output as program input going left to right. - redirect (
<
) (which I call "file as input") taking the contents of a file and using those as if they'd been typed at the command line
Best Answer
I'm often annoyed by the same thing, and there are a few ways of dealing with it:
Just accept it, sometimes it's not worth spending any time to work around it.
as PSkocik mentioned, you can use e.g.
tail -n 5 <(dmesg | grep USB)
Become more adept with your shell's editing capabilities - e.g. in bash (and many other programs that use readline) you can use CtrlA to get to beginning of line, ESCf and ESCb to move forward and back a "word", and Ctrl-XCtrl-E to edit the current line in $EDITOR (e.g.
vim
)There are many more editing commands available and
readline
is fully documented in .info files. On a Debian system, install thereadline-doc
package. Other distros may include the documentation in the readline package itself or may separate it as Debian does.I also recommend installing and using
pinfo
for a more lynx web-browser-like experience (IMO the GNUinfo
browser is ghastly and almost unusable). If it's not already in your distro, you can find it at http://pinfo.alioth.debian.org/readline
also has avi
mode for editing (the default is anemacs
-like mode), which some people prefer.In simple cases, you can use quick substitution: e.g. if the last command you entered was:
dmesg | grep -i USB | tail -n 5
then typing ^USB^sda^Enter would result in this being executed:
dmesg | grep -i sda | tail -n 5
For more details on this, see
man bash
and search forHISTORY EXPANSION
, especially the sectionEvent Designators
.and yes, doing this repeatedly also becomes annoying.
e.g. write a shell script called
dmesg-grep
that looks something like this:Then you can just run
dmesg-grep usb
ordmesg-grep sda
.If you do this a lot, make a
bin
subdirectory of your home directory and add~/bin
to your default PATH (e.g. in~/.bash_profile
or~/.bashrc
) and save your scripts in there.