Reputation: 249
Each line in a given file 'a.txt' contains the directory/path to another unique file. Suppose we want to parse 'a.txt' line-by-line, extract the path in string format, and then use a tool such as vim to process the file at this path, and so on.
After going through this thread - Read a file line by line assigning the value to a variable, I wrote the following script, say 'open-file.sh' on bash (I'm new to it)
#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
vim -c ":q" -cq $line # Just open the file and close it using :q
done < "$1"
We would then run the above script as -
./open-file.sh a.txt
The problem is that although the path to a new file is correctly specified by $line, when vim opens the file, vim continues to receive the text contained in 'a.txt' as a command. How can I write a script where I can correctly obtain the path from 'a.txt', open it using vim, and then continue parsing the remaining lines in 'a.txt' ?
Upvotes: 2
Views: 619
Reputation: 27245
The problem was already mentioned in a comment under the answer you based your script on.
vim
is consuming stdin
which is given to the loop by done < $1
. We can observe the same behavior in the following example:
$ while read i; do cat; done < <(seq 3)
2
3
<(seq 3)
simulates a file with the three lines 1
, 2
, and 3
. Instead of three silent iterations we get only one iteration and the output 2
and 3
.
stdin
is not only passed to read
in the head of the loop, but also to cat
in the body of the loop. Therefore read
reads one line, the loop is entered, cat
reads all remaining lines, stdin
is empty, read
has nothing to read anymore, the loop exits.
You could circumvent the problem by redirecting something to vim
, however there is an even better way. You don't need the loop at all:
< "$1" xargs -d\\n -n1 vim -c :q -cq
xargs
will execute vim
once for every line in the file given by $1
.
Upvotes: 0
Reputation: 896
Although I'm not sure of your ultimate goal, this shell command will execute vim once per line in a.txt
:
xargs -o -n1 vim -c ':q' < a.txt
As explained in the comments to Read a file line by line assigning the value to a variable, the issue you're encountering is due to the fact that vim is an interactive program and thus continues to read input from $line
.
Upvotes: 0
Reputation: 113924
Replace:
vim -c ":q" -cq $line
With:
vim -c ":q" -cq "$line" </dev/tty
The redirection </dev/tty
tells vim
to take its standard input from the terminal. Without that, the standard input for vim
is "$1"
.
Also, it is good practice to put $line
in double-quotes to protect it from word splitting, etc.
Lastly, while vim
is excellent for interactive work, if your end-goal is fully automated processing of each file, you might want to consider tools such as sed
or awk
.
Upvotes: 2