Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question
3  
In case you feel like trying to parse ls output, read this first. –  jw013 Jan 24 '12 at 17:25
add comment

4 Answers

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')"
share|improve this answer
3  
awk way: awk 'NR==2' instead of sed -n '2 p' –  Benoit Jan 24 '12 at 12:43
4  
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 '12 at 12:43
add comment

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

bash someScript.sh | head -2 | tail -1
share|improve this answer
add comment

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

share|improve this answer
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. –  Gilles Jan 24 '12 at 18:29
add comment

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
}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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