Pressing F or G makes less
try to reach input EOF. If the input is a pipe, less
hangs until the pipe is closed on the other side (and not "does nothing").
This can be worked around by saving the command output to a temporary file in the background, and then by using it as input for less
:
command > /tmp/x &
less +F /tmp/x; kill %; rm /tmp/x
There is no option to do this in less
only; however, I admit it would be useful.
First, let's concentrate on performance. I ran benchmarks for a slightly different program on an otherwise mostly idle x86_64 processor running Debian squeeze.
herestring.bash
, using a herestring to pass a line of input:
#! /bin/bash
i=0
while [ $i -lt $1 ]; do
tr a-z A-Z <<<'hello world'
i=$((i+1))
done >/dev/null
heredoc.bash
, using a heredoc to pass a line of input:
#! /bin/bash
i=0
while [ $i -lt $1 ]; do
tr a-z A-Z <<'EOF'
hello world
EOF
i=$((i+1))
done >/dev/null
echo.bash
, using echo
and a pipe to pass a line of input:
#! /bin/bash
i=0
while [ $i -lt $1 ]; do
echo 'hello world' | tr a-z A-Z
i=$((i+1))
done >/dev/null
For comparison, I also timed the scripts under ATT ksh93 and under dash (except for herestring.bash
, because dash doesn't have herestrings).
Here are median-of-three times:
$ time bash ./herestring.bash 10000
./herestring.bash 10000 0.32s user 0.79s system 15% cpu 7.088 total
$ time ksh ./herestring.bash 10000
ksh ./herestring.bash 10000 0.54s user 0.41s system 17% cpu 5.277 total
$ time bash ./heredoc.bash 10000
./heredoc.bash 10000 0.35s user 0.75s system 17% cpu 6.406 total
$ time ksh ./heredoc.bash 10000
ksh ./heredoc.sh 10000 0.54s user 0.44s system 19% cpu 4.925 total
$ time sh ./heredoc.bash 10000
./heredoc.sh 10000 0.08s user 0.58s system 12% cpu 5.313 total
$ time bash ./echo.bash 10000
./echo.bash 10000 0.36s user 1.40s system 20% cpu 8.641 total
$ time ksh ./echo.bash 10000
ksh ./echo.sh 10000 0.47s user 1.51s system 28% cpu 6.918 total
$ time sh ./echo.sh 10000
./echo.sh 10000 0.07s user 1.00s system 16% cpu 6.463 total
Conclusions:
- A heredoc is faster than a herestring.
echo
and a pipe is noticeably, but not dramatically faster. (Keep in mind that this is a toy program: in a real program, most of the processing time would be in whatever the tr
call stands for here.)
- If you want speed, ditch bash and call dash or even better ksh instead. Bash's features don't make up for its relative slowness, but ksh has both features and speed.
Beyond performance, there's also clarity and portability. <<<
is a ksh93/bash/zsh extension which is less well-known than echo … |
or <<
. It doesn't work in ksh88/pdksh or in POSIX sh.
The only place where <<<
is arguably significantly clearer is inside a heredoc:
foo=$(tr a-z A-Z <<<'hello world')
vs
foo=$(tr a-z A-Z <<'EOF'
hello world
EOF
)
(Most shells can't cope with closing the parenthesis at the end of the line containing <<EOF
.)
Best Answer
It's not useless - it's a specialised form of the plain
>
redirect operator (and, perhaps confusingly, nothing to do with pipes).bash
and most other modern shells have an optionnoclobber
, which prevents redirection from overwriting or destroying a file that already exists. For example, ifnoclobber
is true, and the file/tmp/output.txt
already exists, then this should fail:However, you can explicitly override the setting of
noclobber
with the>|
redirection operator - the redirection will work, even ifnoclobber
is set.You can find out if
noclobber
is set in your current environment withset -o
.For the historical note, both the "noclobber" option and its bypass features come from
csh
(late 70s).ksh
copied it (early 80s) but used>|
instead of>!
. POSIX specified theksh
syntax (so all POSIX shells including bash, newer ash derivatives used as sh on some systems support it). Zsh supports both syntaxes. I don't think it was added to any Bourne shell variant but I might be wrong.