Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `ack` not produce output when used with `bash` like this?

Tags:

bash

ack

I'm guessing this has nothing to do with ack but more with bash:

Here we create file.txt containing the string foobar soack can find foobar in it:

> echo foobar > file.txt
> echo 'ack foobar file.txt' > ack.sh
> bash ack.sh
foobar
> bash < ack.sh
foobar

So far so good. But why doesn't ack find anything in it like this?

> cat ack.sh | bash
(no output)

or

> echo 'ack foobar file.txt' | bash
(no output)

Why doesn't ack find foobar in the last two cases?

Adding unbuffer (from expect) in front makes it work, which I don't understand:

> echo 'unbuffer ack foobar file.txt' | bash
foobar

Even stranger:

> cat ack2.sh
echo running
ack foobar file.txt
echo running again
unbuffer ack foobar file.txt

# Behaves as I'd expect
> bash ack2.sh
running
foobar
running again
foobar

# Strange output
> cat ack2.sh | bash
running
unbuffer ack foobar file.txt

What's up with this output? It echos unbuffer ack foobar file.txt but not running again? Huh?

like image 612
Peter V. Mørch Avatar asked Jul 14 '17 05:07

Peter V. Mørch


People also ask

How does ACK work in Linux?

Ack searches the named input FILEs (or standard input if no files are named, or the file name - is given) for lines containing a match to the given PATTERN . By default, ack prints the matching lines.

Why does ACK give Me output I'm Not expecting?

If ack gives you output you're not expecting, start with a few simple steps. Your environment variables and .ackrc may be doing things you're not expecting, or forgotten you specified. Use --noenv to ignore your environment and .ackrc . The reason I created -f in the first place was as a debugging tool.

Why won't ACK select all files with-a?

With no file selections, ack only searches files of types that it recognizes. If you have a file called foo.wango, and ack doesn't know what a .wango file is, ack won't search it. The -a option tells ack to select all files, regardless of type. Some files will never be selected by ack, even with -a, including:

How do I get the output of Ack from a program?

Direct ack's output through program. This can also be specified via the "ACK_PAGER" and "ACK_PAGER_COLOR" environment variables. Using --pager does not suppress grouping and coloring like piping output on the command-line does.


1 Answers

ack gets confused because stdin is a pipe rather than a terminal. You need to pass the --nofilter option to force ack to treat stdin as a tty.

This:

# ack.sh
ack --nofilter foobar file.txt

works:

$ cat ack.sh | bash
foobar

If you ask me, that behaviour is quite unexpected. Probably it is expected when someone understand the concepts of ack which I do not atm. I would expect that ack doesn't look at stdin when filename arguments are passed to it.


Why does unbuffer "solve" the problem?

unbuffer, following it's man page, does not attempt to read from stdin:

  Normally, unbuffer does not read from stdin.  This  simplifies  use  of
   unbuffer in some situations.  To use unbuffer in a pipeline, use the -p
   flag. ...

Looks like ack tries to be too! smart about stdin here. If it is empty it does not read from stdin and looks at the filenames passed to it. Again, imo it would be correct to not look at stdin at all if filename arguments are present.

like image 158
hek2mgl Avatar answered Oct 02 '22 02:10

hek2mgl