26

Assuming a script that outputs a list of files:

$> bash someScript.sh
path/to/some/file
path/to/the/file/i/want/to/work/with
path/to/yet/another/file

Now I want to have the second file-path as parameter for another command, e.g. vim. Is there a way to directly access it?

And I want to point out that I do not necessarily want to access the second file, but the next time it could be the third or the 27th. I want to be able to select that Nth line as easily as possible.

Right now I do mouse-selecting and insert by middle-clicking or type the path with tab-completion. Now I wonder if there is an easier way.

Problem with my own solution is though that I would have to edit all my scripts this way. It would be fun if there was a more general solution to this issue, that would work with any kind of command, e.g. find.

2

5 Answers 5

41

Sure.

bash someScript.sh | sed -n '2 p'

will filter your output and just print the second line of it. To make that a parameter to vim:

vim "$(bash someScript.sh | sed -n '2 p')"
2
  • 8
    awk way: awk 'NR==2' instead of sed -n '2 p'
    – Benoit
    Jan 24, 2012 at 12:43
  • 13
    As the question is tagged efficiency, better stop sed ASAP: sed -n '2{p;q}'. This avoids reading the remainder of output in vain. @Benoit, similarly for awk: awk 'NR==2{print;exit}.
    – manatwork
    Jan 24, 2012 at 12:43
15

Use head and tail, e.g. accessing the 2nd line of an output:

bash someScript.sh | head -2 | tail -1
1
  • 1
    tail +N | head -n 1 works better because if N is greater than the total lines, it outputs nothing, instead of the last line
    – Juan Campa
    Nov 17, 2020 at 13:12
3

If being short to type is paramount and the file isn't very large:

nth_line=$(sed -n ${n}p)
nth_line=$(sed \!${n}d)

If the file is long and you're only interested in one line, use sed to print the desired line and quit, or tail to remove the previous lines and head to extract the first line of the result.

nth_line=$(sed -n -e "$n {" -e p -e q -e "}")
nth_line=$(tail -n +$n | head -n 1)

(Note that tail -n +$n skips n-1 lines, i.e. its output starts with the nth line.)

For a small number of lines, you can use the read built-in.

IFS= read -r first_line; IFS= read -r second_line

If you want to read all lines, you can put them in an array (ksh/bash/zsh only).

IFS=$'\n'
lines=($(cat))
second_file="${lines[1]}"  # note that ksh/bash arrays start at 0

If you want to make this reusable code, put it in a function.

# Read at most MAX input lines (default: all) into the VAR array (default: ${lines[@]}).
# Usage: read_lines [VAR [MAX]]
read_lines () {
  typeset IFS=$'\n'
  if [ $# -eq 0 ]; then set lines; fi
  if [ -z "$2" ]; then eval "$1=(\$(cat))"; else eval "$1=(\$(head -n $2))"; fi
}
1

Below are the two better ways to print nth line of text files in linux.

  1. Use the combination of head and tail command

    One of the easiest way of printing nth line of a text file is by using the combination of head and tail command.Below is an exapmle of how to use it for displaying the 9th line of a file named sample.txt

    cat sample.txt | head -9 | tail -1
    

    If you want to display 9th and 10th line replace the value of tail to 2 as below.

    cat sample.txt | head -9 | tail -2
    
  2. using sed command

    There are two ways to do this with sed command. One is with using p (print) and other is with using d (delete) along with sed command. Following are the examples

    cat sample.txt | sed -n '9p'     # This will display the 9th line of sample.txt file
    cat sample.txt | sed -n '9p;12p' # This will display 9th and 12th line of  sample.txt
    

    Likewise we can display as much of line of a file as per our need.

    cat sample.txt | sed '9!d'       # This will display the 9th line of sample.txt
    

http://tecmint4u.blogspot.com/2020/10/how-to-get-nth-line-of-text-file-in.html

0

I solved it even though it's a bit hackish ;)

That's the script outputting file paths:

#!/bin/bash
rm /tmp/svn_filelist_to_source /tmp/svn_filelist
svn status | egrep 'M |A ' | cut -c9- > /tmp/svn_filelist
counter=1
cat /tmp/svn_filelist | while read -r path; do
  echo $path
  echo "file$counter=\"$path\"" >> /tmp/svn_filelist_to_source
  counter=$(($counter+1))
done;

Here's how I run it, which I think I'll put in an alias:

sh statusAddedAndModified.sh && source /tmp/svn_filelist_to_source

Now I can:

svn commit $file2

1
  • 2
    Use IFS= read -r unless you mean to strip leading and trailing whitespace (explanation). There are shorter and faster ways to grab all lines; see my answer. Jan 24, 2012 at 18:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.