0

Situation: I want a one line command that can pull out the latest log (updates hourly), and watch as it changes. Here's an attempt that might explain less obscurely:

tail -500f $(ls | grep PackageName | sort | tail -1)

The above approach works actually, however when I create an alias for it, it doesn't update the $(~~~) value. Can anyone suggest a reason for it?

So, another attempt (the point of this question):

ls | grep PackageName | sort | tail -1 | tail -500f (LogFileNameTimeStampLatest)

Turns out it just outputs the result from last pipe (LogFileNameTimeStampLatest). And it makes sense as well, because that's what the 2nd last pipe command (tail -1 was doing in the first place)

I wanted to understand how would one use the output from last pipe to point to a file in the next pipe (and not just the LogFileName). Concretely, how would one use an output of one pipe as an argument for another pipe?

Rohan Kumar
  • 726
  • 10
  • 17
  • When you defined the alias, did you enclose it in single-quotes or double-quotes? You want single-quotes; double-quotes would give the result you describe. But functions are generally better than aliases (see @tripleee's answer). – Gordon Davisson Feb 05 '19 at 07:47
  • What are some trade-offs to using an alias? – Rohan Kumar Feb 07 '19 at 11:35
  • 1
    Aliases are ok for really simple shortcuts (e.g. `alias ll='ls -l'`), but for anything nontrivial a function is the way to go. See [this AskUbuntu question](https://askubuntu.com/questions/163882/alias-vs-function-in-bash-scripts) for more discussion and differences. – Gordon Davisson Feb 07 '19 at 19:33

1 Answers1

3

Don't create an alias. Create a function.

watchlog () {
    tail -500f "$(ls *PackageName* | sort | tail -1)"
}

The double quotes are necessary if the output contains file names which themselves contain shell metacharacters, including any spaces.

There are probably good ways to avoid the use of ls in a script but the trivial solution is to just not attempt to put this in an alias.

The same command could be rephrased with xargs which I guess is what you are trying to ask last:

ls *PackageName* | sort | tail -1 |
xargs tail -500f
tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Hi! I followed your advice to create a function as you suggested. However, the command doesn't update itself for logs forming in the subsequent hours. I can't figure out which param or arg I'm not doing right. – Rohan Kumar Feb 07 '19 at 11:32
  • And thanks for the `xargs` tip! Currently my method looks like: `eplog() { tail -500f "$(cd /deploy/var/env/SummerEndWebsite/output/logs/ && find SummerEndWebsite* | sort | tail -1)" }` – Rohan Kumar Feb 07 '19 at 11:34
  • 1
    The `cd` looks weird, won't it stop working if you run it in the wrong directory? Better to do `find /deploy/var/env/etc -maxdepth 1 -name 'SummerEndWebsite*' | sort | tail -n 1` – tripleee Feb 07 '19 at 12:03
  • 'cd' looks weird I know, I just wanted to be able to `cd` into that directory as well, so I chose to write it that way. One could use `find` like you mentioned and get away with never needing `cd`. Also, `cd` gets an absolute path so I'm not really sure how changing directory would affect it's behaviour. – Rohan Kumar Feb 08 '19 at 05:15
  • That's what I'm saying, the output from `find` will refer to a different directory than the one where the outer `tail` runs so you will get "file not found". – tripleee Feb 08 '19 at 05:16
  • Wouldn't the change-directory from the inner `cd` affect the directory path of the outer `tail`. Seems like I made this implicit assumption - that the outer `find` recognizes that the `cd` changed directory in the inside. – Rohan Kumar Feb 08 '19 at 05:21
  • And that it wasn't the right assumption to make. – Rohan Kumar Feb 08 '19 at 05:21
  • No, a subprocess cannot affect its parent. – tripleee Feb 08 '19 at 05:22