2

When I run a command like tail ~/SOMEFILE I get, for example:

testenv@vps_1:~# tail ~/SOMEFILE
    This is the content of SOMEFILE.

But what if I want to have a carriage return between: testenv@vps_1:~# and the output of: This is the content of SOMEFILE.

So the final result would be like this:

testenv@vps_1:~# tail ~/SOMEFILE

    This is the content of SOMEFILE.

Or this:

testenv@vps_1:~# tail ~/SOMEFILE


    This is the content of SOMEFILE.

Or this:

testenv@vps_1:~# tail ~/SOMEFILE



    This is the content of SOMEFILE.

Note: The first example show one line of spacing between the two parts, the second example show two lines, and the third three lines.

Is there a way to make sure the tail output (or any other output) for that matter would be spaced down as I've shown in the examples, just for this particular command (not for all commands of course), in Bash?

3 Answers3

3

tail doesn't have any argument to manage this.

What you can do as a workaround is printing one empty line before running the tail command.

echo && tail ~/SOMEFILE

For multiple lines: yes command can also be used. yes man page like suggested here: bash: print x number of blank lines

yes '' | sed 5q && tail ~/SOMEFILE

Replace 5 by the amount of empty lines you want.

Note: you may also want to have a look at editing your terminal prompt. But then it will be terminal wide and not only linked to your specific command.

  • Hmm, nice, I wonder if instead doing echo && echo && echo && tail there is an even more aesthetic trick to add multiple empty lines (maybe there's a way to multiply an echo or any other command for that matter). – Arcticooling Dec 21 '17 at 13:31
  • I've edited the answer for multiple lines. – Kevin Lemaire Dec 21 '17 at 13:45
1

For single empty line

sed '{x;1p;x;}' filename | tail

For 5 empty lines at the beginning

sed '{x;1p;1p;1p;1p;1p;x;}' filename | tail
grg
  • 197
1

The simplest option would be printing manually those extra newlines, something like:

printf '\n\n\n'; tail ~/SOMEFILE

But if you want to:

  • Do this just for tail
  • Not write extra commands with every tail invocation
  • Have a simple yet full control over the quantity of newlines

then I recommend you to add a function to your aliases/rc file.

For example:

# Bash version

# In Bash we can override commands with functions
# thanks to the `command` builtin
tail() {

  # `local` limit the scope of variables,
  # so we don't accidentally override global variables (if any).
  local i lines

  # `lines` gets the value of the first positional parameter.
  lines="$1"

  # A C-like iterator to print newlines.
  for ((i=1; i<=lines; i++)); do
    printf '\n'
  done

  # - `command` is a bash builtin, we can use it to run a command.
  #   whose name is the same as our function, so we don't trigger
  #   a fork bomb: <https://en.wikipedia.org/wiki/Fork_bomb>
  #
  # - "${@:2}" is to get the rest of the positional parameters.
  #   If you want, you can rewrite this as:
  #
  #       # `shift` literally shifts the positional parameters
  #       shift
  #       command "${@}"
  #
  #   to avoid using "${@:2}"
  command tail "${@:2}"

}

#===============================================================================

# POSIX version

# POSIX standard does not demand the `command` builtin,
# so we cannot override `tail`.
new_tail() {

  # `lines` gets the value of the first positional parameter.
  lines="$1"

  # `i=1`, `[ "$i" -le "$lines" ]` and `i=$((i + 1))` are the POSIX-compliant
  # equivalents to our C-like iterator in Bash
  i=1
  while [ "$i" -le "$lines" ]; do
    printf '\n'
    i=$((i + 1))
  done

  # Basically the same as Bash version
  shift
  tail "${@}"

}

So you can call it as:

tail 3 ~/SOMEFILE
nxnev
  • 3,654
  • wow... This code seems so different than JavaScript or PHP flow control... What's local i lines abd command tail "${@:2}" and while [ "$i" -le "$lines" ]; do? Or you know what? Please don't answer these questions. You are more than welcome to just add comments to some parts of the script. :) And thank you anyway! – Arcticooling Dec 21 '17 at 19:55
  • @pntshere I apologize, I'll try to add explanatory comments to my code from now on. I tend to forget that shell language is very counterintuitive even for experienced programmers, mostly because it's, practically, the only language I've ever used extensively so I just get used to its weirdness. But I think is worth to say a few things about shell scripting. – nxnev Dec 21 '17 at 22:10
  • @pntshere Shell code gets unreadable and unreliable easily. Like it or not, that's the norm. It's too easy to blown away your (and others') entire system just because you forget to quote your variables, your error handling has some flaws or some clueless developer misplaced a space somewhere. Even David Korn (the author of ksh, a very popular interpreter in the 80-90's) has problems with writing robust and reliable shell code. – nxnev Dec 21 '17 at 22:11
  • @pntshere Just take a look at this page: a collection of 50 common errors that shell programmers make. Most of them are unnoticeable for newcomers because they look right and seem logical. Shell is just some peculiar command interpreter whose syntax has been modified over the years to resemble more like any typical programming language. But it is not your typical programming language. If you ever aim to achieve some robust knowledge about shell, sooner or later you'll have to deal with that kind of weirdness. – nxnev Dec 21 '17 at 22:11
  • Much thanks for this description. Only one last small question, please. You wrote It's too easy to blown away your (and others') entire system just because you forget to quote your variables. I admit I'm aware that one should take extra caution when deleting anything in server environments as with rm for example, because there's no way back if there's no backup, but what do you mean to in regards to quote marks? Of course, it's not sudo rm -rf /*... So, I wonder what you meant there. – Arcticooling Dec 21 '17 at 22:22
  • @pntshere Let's say you are a developer writing a deployment script for your software. Your script needs sudo rights to do stuff with docs, config files, binaries and all that jazz, and you need to replace some old files with new files (nothing critical; documentation, for example). But your script has two very typical flaws: your var's value has a trailing space and that same var is unquoted in the rm statement. Something like this, but with rm instead of printf: dir="/path/to/dir "; printf '%s\n' $dir/*. So just imagine what will happen if your users run your script. – nxnev Dec 21 '17 at 23:09
  • @pntshere By the way, you don't need to literally run sudo rm -rf /* to broke your PC. You can even do it by accidentally changing one single character (a common typo) when attempting to burn the ISO of that brand-new Linux distribution you've heard about (/dev/sda instead of /dev/sdb). – nxnev Dec 21 '17 at 23:11
  • @pntshere, for a more in-depth answer to that question, see Security implications of forgetting to quote a variable in bash/POSIX shells – Wildcard Dec 21 '17 at 23:32
  • @Wildcard I've actually linked that answer in the "quote your variables" link. – nxnev Dec 21 '17 at 23:56