32

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

6 Answers 6

56

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
  • 10
    awk way: awk 'NR==2' instead of sed -n '2 p'
    – Benoit
    Commented Jan 24, 2012 at 12:43
  • 18
    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
    Commented Jan 24, 2012 at 12:43
18

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
    Commented Nov 17, 2020 at 13:12
4

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. Commented Jan 24, 2012 at 18:29
0

Using Raku (formerly known as Perl_6)

Read 2nd line (zero-index == 1):

raku -ne '.put if $++ == 1'

#OR:

raku -e 'lines[1].put' 

Read line# determined by env variable:

env desired_line="1" raku -ne '.put if $++ == %*ENV<desired_line> ;'

#OR: 

env desired_line="1" raku -e 'lines[ %*ENV<desired_line> ].put;'

Above are answers written in Raku, a member of the Perl family of programming languages. Input is taken either via STDIN, or off the command line (both answers). In the first set

In the first set of answers, line number is hard-coded. In the second set of answers, the line number can be determined from a shell variable. Raku has a special associative array %*ENV which can be used to access shell variables.

Raku has an awk-like mode invoked with the -ne command-lane flags. Here, anonymous pre-incrementing (++$) or post-incrementing ($++) variables can be used to count line numbers (and many other things as well).

Using the OP's example input:

~$ printf 'path/to/some/file\npath/to/the/file/i/want/to/work/with\npath/to/yet/another/file' | raku -e 'lines[1].put'
path/to/the/file/i/want/to/work/with

OR:

~$ printf 'path/to/some/file\npath/to/the/file/i/want/to/work/with\npath/to/yet/another/file' | env desired_line="1" raku -e 'lines[ %*ENV<desired_line> ].put'
path/to/the/file/i/want/to/work/with

Finally, see "Raku Input/Output: the definitive guide" on how to use Raku to extract/grep target lines, words, etc., from files that are too big to fit into RAM.

https://docs.raku.org/routine/lines
https://raku.org

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .