i'm trying to write a bash script and i don't get the result displayed in the terminal - linux

i'm trying to display the 3rd to the 7th line from a file but i get nothing displayed in the terminal i'm using this command :
head -n 7 /etc/passwd | tail -n +3
i want the result be seen in the terminal .

You can try this way
head -n 7 /etc/passwd | tail -n 5
For example :
seq 20 | head -n 7 | tail -n 5
Output :
3
4
5
6
7
Explanation :
head -n 7 -- print the first 7 lines ( so 1..7 printed)
tail -n 5 -- print last 5 lines ( so skipped first two lines 3..7 printed )

head -n 7 /etc/passwd | tail -n +3
Seems to do exactly what you want it to do for me. Have you verified the contents of /etc/passwd? If you do not have permission to read the file or it is empty you will get no output.
I would check other places in the script. Change the first line of your script to:
#!/bin/bash -v
to have it echo the commands so you can make sure what you think is being executed actually is.

What do you get than ? Show the file output, but choose another file ;)
It sometimes helps to just change commands, try with either HEAD or TAIL twice, to come to the same result.

Related

Fixing invalid number of lines in tail by passing an integer into tail

Running Centos8.
Here is my current (tiny) script:
#!/usr/bin/env bash
x=$((($2-$1)+1))
head -n $2 $3 | tail -n -$x
As an example of an input:
sh script.sh 7 10 /etc/passwd
And what I am trying to get out is lines 7-10 from /etc/passwd.
It should be fairly simple, because just doing
head -n 7 /etc/passwd | tail -n -4
Returns those 4 lines perfectly fine.
However, using $x (to get the input from the second number, minus the first, plus 1), fails. Whenever I run this code I get this error:
tail: invalid number of lines: ‘4\r\r’
Which from my understanding means that the code is not accepting the $x input from the small math I did, and thinks that its 4 with two trailing spaces?
How would I go about fixing this issue, so that the four lines of /etc/password get listed?
There's problem on line 3
#!/usr/bin/env bash
x=$((($2-$1)+1))
head -n $1 $3 | tail -n -$x
That needs to say $1, not $2.
And the line endings are Mac, not Linux.

Bash script and manually running commands on the command line

I have the following simple bash script which takes input from stdin and prints the third line given as input.
#!/bin/bash
var=$(cat)
echo $var | head -n 3 | tail -n 1
The problem with this script is that it prints all the lines but here is the funny part, when I type the commands individually on the command line I am getting the expected result i.e. the third line. Why this anomaly? Am I doing something wrong here?
The aim of head -n 3 | tail -n 1 is to keep the third line into variable
It will be more efficient to use read builtin
read
read
read var
echo "${var}"
Or to keep heading white-spaces
IFS= read
and not join lines ending with \ or not give special meaning to \
read -r
You don't need $(cat) in your script. If script is reading data from stdin then just have this single line in your script:
head -n 3 | tail -n 1
And run it as:
bash myscript.sh < file.txt
This will print 3rd line from file.txt
PS: You can replace head + tail with this faster sed to print 3rd line from input:
sed '3q;d'
The shell is splitting the var variable so echo get multiple parameters. You need to quote your variable to prevent this to happen:
#!/bin/bash
var=$(cat)
echo "$var" | head -n 3 | tail -n 1
This should do the trick, as far as I understand your question:
#!/bin/bash
var=$(cat)
echo "$var" | head -n 3 | tail -n 1
var=$(cat) will not allow you to escape out of stdin mode. you need to specify the EOF for the script to understand to stop reading from stdin.
read -d '' var << EOF
echo "$var" | head -n 3 | tail -n 1

bash script - print X rows from a seleccted file from a folder

I'm trying to write a script which help to follows the logs of my application.
The logs of my application are written to "var/log/MyLogs/" with the following pattern:
runningNumber_XXX.txt , for example:
0_XXX.txt
37_xxx.txt
99_xxx.txt
101_xxx.txt
103_xxx.txt
I'm trying to write a bash script (without a success for now) which will print last 20 rows of the last log file (the last log file is the file with has the biggest prefix number).
I know I need to go over the files in the folder (for file in /var/log/MyLogs/*) and check which file name has the biggest prefix, and after it print the last 20 rows from the selected file.
please help me....
Thanks...
find /var/log/MyLogs -iname '*_xxx.txt' | sort -n | tail -1 | xargs tail -20
Get correct files
Sort numerically
Get last log file
Get last 20 rows
tail -20 $(ls -1 /var/log/MyLogs/*_*.txt | sort -n -t _ -k 1 -r | head -1)
ls -1 [0-9]*_XXX.txt | sort -rn | head -1 | xargs tail -20
Usually is the bad practice using ls in shell scripts, but if you can ensure than the logfiles doesn't contains spaces and other strange characters, you can use a simple:
tail -20 $(ls -t1 /var/log/[0-9]*_XXX.txt | head -1)
The:
ls -t sorts the files my modification time newest comes first
head the the 1st
tail print the last lines
AGAIN, this is usually a bad practice, you can use it only when you knows what you're doing.

Show surrounding lines of a specific line via linux command line

Right now I am running:
head -1274954 /path/to/dump.sql | tail -1
This shows me one line, I'd like to see 10 lines above and 10 lines below it.
Why not just:
$ head -1274964 /path/to/dump.sql | tail -20
?
Check $ man head
NAME
head - output the first part of files
Check $ man tail
NAME
tail - output the last part of files
You are piping (|) output of head command to tail command.
That's why it is printing last line from first 1274954 lines.
$ head -1274964 /path/to/dump.sql | tail -20
It will generate output upto lines 1274964 and pipe it to tail command which will print 20 lines which are at the bottom of your output of head command.

first two results from ls command

I am using ls -l -t to get a list of files in a directory ordered by time.
I would like to limit the search result to the top 2 files in the list.
Is this possible?
I've tried with grep and I struggled.
You can pipe it into head:
ls -l -t | head -3
Will give you top 3 lines (2 files and the total).
This will just give you the first 2 lines of files, skipping the size line:
ls -l -t | tail -n +2 | head -2
tail strips the first line, then head outputs the next 2 lines.
To avoid dealing with the top output line you can reverse the sort and get the last two lines
ls -ltr | tail -2
This is pretty safe, but depending what you'll do with those two file entries after you find them, you should read Parsing ls on the problems with using ls to get files and file information.
Or you could try just this
ls -1 -t | head -2
The -1 switch skips the title line.
You can use the head command to grab only the first two lines of output:
ls -l -t | head -2
You have to pipe through head.
ls -l -t | head -n 3
will output the two first results.
Try this:
ls -td -- * | head -n 2

Resources