ReDevil
ReDevil

Reputation: 77

unix tty hang after tail with acute (`)

Hi i run a command on Linux server.

tail -3 `ls -1t nnnn* | head -1`

When nnnn file exist, all good.

When nnnn file not exist the tty is hanged until ^C

nt-home-stg>> tail -3 `ls -1t nnnn* | head -1`
ls: No match.

After the ls: No match. it hangs until ctrl c (^c) is pressed.

I've searched the web and could not find an answer.

Already tried the traditional suppress >& /dev/null and 2>/dev/null . Did not help.

Is there a way for the command to end and not hang?

Upvotes: 1

Views: 256

Answers (1)

IMSoP
IMSoP

Reputation: 97638

The backtick syntax substitutes the output of the given command; when that command returns a filename, you get something like:

tail -3 nnnn01.whatever

But if there are no matches, there is nothing to substitute, so you effectively run:

tail -3

If we look at the summary under man tail, we see the behaviour if tail is not given a filename:

With no FILE, or when FILE is -, read standard input.

So tail is waiting for some input to be piped in, and it will then display the last 3 lines of that input. You can actually type a few lines of text, and press Ctrl-D ("end of file"), and you'll see it happen.

This may seem pointless, but the command doesn't know (or care) that it's been invoked directly, and not as part of a pipeline. So the head -1 in your inner query is actually doing the same thing: reading standard input because you didn't give a file name.

To avoid this, you should test that your file exists first, before running tail. A non-elegant way of writing that on one line would be to capture the filename in a variable, and use [ (aka test) to assert that it is non-empty:

(file=`ls -1t nnnn* | head -1`; [ -n "$file" ] && tail -3 $file)

This will still give you the warning from ls that the glob failed, but will skip the hanging tail.

Upvotes: 2

Related Questions