Tux

...making Linux just a little more fun!

2-cent Tip: Conditional pipes

Ben Okopnik [ben at linuxgazette.net]


Mon, 3 Aug 2009 22:43:05 -0500

In using Debian/Ubuntu, I often find myself doing an "apt-cache search <foo>" - i.e., searching the package database. Unfortunately, the copious return from the search often overruns my screen, requiring paging up - or, if I do remember to pipe the output to 'less', turns out to be annoyingly short (and now requires quitting out of the pager.) So, a little while ago, I decided to be lazy^Wefficient and write a script... actually, a function - a script wouldn't do, since the variable I'm looking for only exists in the current shell environment.

From my ~/.bashrc:

ac () 
{ 
    out=$(/usr/bin/apt-cache search "$@")
    if [ $(($(echo "$out"|/usr/bin/wc -l)+2)) -ge $LINES ]
	then
        echo "$out" | /usr/bin/less
    else
        echo "$out"
    fi
}
export -f ac

Using the $LINES Bash variable, which tells us how many lines our current terminal is capable of displaying, makes it relatively simple to decide whether to use a pipe or not. I also adjust the comparison a bit to account for the prompt.

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back


Mulyadi Santosa [mulyadi.santosa at gmail.com]


Tue, 4 Aug 2009 11:06:05 +0700

On Tue, Aug 4, 2009 at 10:43 AM, Ben Okopnik<ben@linuxgazette.net> wrote:

> In using Debian/Ubuntu, I often find myself doing an "apt-cache search
> <foo>" - i.e., searching the package database. Unfortunately, the
> copious return from the search often overruns my screen, requiring
> paging up - or, if I do remember to pipe the output to 'less', turns out
> to be annoyingly short (and now requires quitting out of the pager.) So,
> a little while ago, I decided to be lazy^Wefficient and write a
> script... actually, a function - a script wouldn't do, since the
> variable I'm looking for only exists in the current shell environment.
> From my ~/.bashrc:
>
> ```
> ac ()
> {
>    out=$(/usr/bin/apt-cache search "$@")
>    if [ $(($(echo "$out"|/usr/bin/wc -l)+2)) -ge $LINES ]
>        then
>        echo "$out" | /usr/bin/less
>    else
>        echo "$out"
>    fi
> }
> export -f ac
> '''
>
> Using the $LINES Bash variable, which tells us how many lines our
> current terminal is capable of displaying, makes it relatively simple to
> decide whether to use a pipe or not. I also adjust the comparison a bit
> to account for the prompt.

Hi Ben, how about simply use less -F? e.g:

$ seq 1 5 | less -F
1
2
3
4
5
[pager immediately quits here]

Does this serve the same purpose in your opinion?

regards,

-- 
Mulyadi Santosa
Freelance Linux trainer
blog: the-hydra.blogspot.com


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Mon, 3 Aug 2009 23:56:51 -0500

On Tue, Aug 04, 2009 at 11:06:05AM +0700, Mulyadi Santosa wrote:

> 
> Hi Ben, how about simply use less -F? e.g:
> $ seq 1 5 | less -F
> 1
> 2
> 3
> 4
> 5
> [pager immediately quits here]
> 
> Does this serve the same purpose in your opinion?

Mine definitely doesn't do anything like the above:

ben@Jotunheim:~$ seq 5|less -F
ben@Jotunheim:~$

Presumably, it's doing what the man page says: exits if the output is less than a page long.

-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back


Mulyadi Santosa [mulyadi.santosa at gmail.com]


Tue, 4 Aug 2009 17:08:40 +0700

On Tue, Aug 4, 2009 at 11:56 AM, Ben Okopnik<ben@linuxgazette.net> wrote:

> On Tue, Aug 04, 2009 at 11:06:05AM +0700, Mulyadi Santosa wrote:
>>
>> Hi Ben, how about simply use less -F? e.g:
>> $ seq 1 5 | less -F
>> 1
>> 2
>> 3
>> 4
>> 5
>> [pager immediately quits here]
>>
>> Does this serve the same purpose in your opinion?
>
> Mine definitely doesn't do anything like the above:
>
> ```
> ben@Jotunheim:~$ seq 5|less -F
> ben@Jotunheim:~$
> '''
>
> Presumably, it's doing what the man page says: exits if the output is
> less than a page long.

Pffff...wonder why.... different version of less package perhaps? Mine is:

$ rpm -qf /usr/bin/less
less-418-3.fc9.i386

regards,

-- 
Mulyadi Santosa
Freelance Linux trainer
blog: the-hydra.blogspot.com


Top    Back


Jim Jackson [jj at franjam.org.uk]


Tue, 4 Aug 2009 22:34:10 +0100 (BST)

On Mon, 3 Aug 2009, Ben Okopnik wrote:

> On Tue, Aug 04, 2009 at 11:06:05AM +0700, Mulyadi Santosa wrote:
>>
>> Hi Ben, how about simply use less -F? e.g:
>> $ seq 1 5 | less -F
>> 1
>> 2
>> 3
>> 4
>> 5
>> [pager immediately quits here]
>>
>> Does this serve the same purpose in your opinion?
>
> Mine definitely doesn't do anything like the above:
>
> ```
> ben@Jotunheim:~$ seq 5|less -F
> ben@Jotunheim:~$
> '''
>
> Presumably, it's doing what the man page says: exits if the output is
> less than a page long.

Behaviour varies depending on the setting of the TERM environment variable

$ export TERM=vt220
$ seq 5 | less -F
1
2
3
4
5
$ 

whereas ...

$ export TERM=xterms
$ seq 5 | less -F
$

The output is generated, as can be seen by using script to capture the output...

$ script
Script started, file is typescript
$ export TERM=xterms
$ seq 5 | less -F
$ exit
exit
Script done, file is typescript

Investigating the typescript file with less shows the gory details. Unfortunately I'm not too sure what the xterm control sequences do, but there's abunch of them there, that are there if your have set TERM to vt220.

cheers Jim


Top    Back


Thomas Adam [thomas.adam22 at gmail.com]


Tue, 4 Aug 2009 23:02:56 +0100

2009/8/4 Jim Jackson <jj@franjam.org.uk>:

> Investigating the typescript file with less shows the gory details.
> Unfortunately I'm not too sure what the xterm control sequences do, but
s/xterm control sequences/termcap init sequences/

Which basically set the initial terminal state (*some* of those control sequences will be setting line type which is what you want to inhibit here) -- and, oh look:

[n6tadam@shuttle][~]% seq 5 | LESS=FX less && echo "$TERM"
1
2
3
4
5
rxvt-unicode

Don't bugger about with TERM. Use less the way it's meant to. That is, here, "X" which stops the init of the termcap being sent to the terminal.

-- Thomas Adam


Top    Back


Jim Jackson [jj at franjam.org.uk]


Wed, 5 Aug 2009 12:02:14 +0100 (BST)

On Tue, 4 Aug 2009, Thomas Adam wrote:

> 2009/8/4 Jim Jackson <jj@franjam.org.uk>:
>
>> Investigating the typescript file with less shows the gory details.
>> Unfortunately I'm not too sure what the xterm control sequences do, but
>
> s/xterm control sequences/termcap init sequences/
>
> Which basically set the initial terminal state (*some* of those
> control sequences will be setting line type which is what you want
> to inhibit here) -- and, oh look:
>
> ``
> [n6tadam@shuttle][~]% seq 5 | LESS=FX less && echo "$TERM"
> 1
> 2
> 3
> 4
> 5
> rxvt-unicode
> ''
>
> Don't bugger about with TERM.  Use less the way it's meant to.  That
> is, here, "X" which stops the init of the termcap being sent to the
> terminal.

Just to set the record straight, I didn't advocate "bugger"ing about with TERM setting as a solution to the "less-swallowing-the-page" problem, I was merely pointing out why 2 people invoking less in the same way got different results. I also thought it might be a pointer towards a solution for those who knew how to drive less - and the solution is a goer.

cheers

Jim


Top    Back


Mulyadi Santosa [mulyadi.santosa at gmail.com]


Thu, 6 Aug 2009 00:38:00 +0700

On Wed, Aug 5, 2009 at 6:02 PM, Jim Jackson<jj@franjam.org.uk> wrote:

>
>
>
> On Tue, 4 Aug 2009, Thomas Adam wrote:
>
>> 2009/8/4 Jim Jackson <jj@franjam.org.uk>:
>>
>>> Investigating the typescript file with less shows the gory details.
>>> Unfortunately I'm not too sure what the xterm control sequences do, but
>>
>> s/xterm control sequences/termcap init sequences/
>>
>> Which basically set the initial terminal state (*some* of those
>> control sequences will be setting line type which is what you want
>> to inhibit here) -- and, oh look:
>>
>> ``
>> [n6tadam@shuttle][~]% seq 5 | LESS=FX less && echo "$TERM"
>> 1
>> 2
>> 3
>> 4
>> 5
>> rxvt-unicode
>> ''
>>
>> Don't bugger about with TERM. Use less the way it's meant to. That
>> is, here, "X" which stops the init of the termcap being sent to the
>> terminal.
>
> Just to set the record straight, I didn't advocate "bugger"ing about with
> TERM setting as a solution to the "less-swallowing-the-page" problem, I was
> merely pointing out why 2 people invoking less in the same way got different
> results. I also thought it might be a pointer towards a solution
> for those who knew how to drive less - and the solution is a goer.
>
> cheers
> Jim

Thanks a lot for all the explanations. Now I know a bit more about console, less and TERM :) So much to learn, so little time ...

regards,

-- 
Mulyadi Santosa
Freelance Linux trainer
blog: the-hydra.blogspot.com


Top    Back


Ben Okopnik [ben at linuxgazette.net]


Thu, 6 Aug 2009 18:36:14 -0500

On Tue, Aug 04, 2009 at 11:02:56PM +0100, Thomas Adam wrote:

> 
> ``
> [n6tadam@shuttle][~]% seq 5 | LESS=FX less && echo "$TERM"
> 1
> 2
> 3
> 4
> 5
> rxvt-unicode
> ''
> 
> Don't bugger about with TERM.  Use less the way it's meant to.

An unnecessarily crude way of putting it, but technically sound. How did you get so smart, Thomas? :)

> That
> is, here, "X" which stops the init of the termcap being sent to the
> terminal.

Nice solution. Therefore, my tct: 2-cent tip is reduced to

ac () { /usr/bin/apt-cache search "$@"|LESS=FX /usr/bin/less; }
export -f ac
-- 
* Ben Okopnik * Editor-in-Chief, Linux Gazette * https://LinuxGazette.NET *


Top    Back


Thomas Adam [thomas.adam22 at gmail.com]


Fri, 7 Aug 2009 00:41:32 +0100

2009/8/7 Ben Okopnik <ben@linuxgazette.net>:

> An unnecessarily crude way of putting it, but technically sound. How did
> you get so smart, Thomas? :)

The previous use of "export TERM" was the problem moreover setting TERM locally to a command:

TERM=foo command

Which not all shells appreciate (and neither came out in the original example of the solutions posted). I realise that. It would then have left the environment completely rotten, especially for subsequent commands such as vim.

Yeah, I am sure it reads as "harsh", but hey... I'm still learning to spit acid to go with it, so until then... :)

-- Thomas Adam


Top    Back