-
function test_do()
{
local list="$1"
local item
while IFS= read -r item
do
#nano "$item" # this crashes
echo "$item"
done < $list
}
function test_prepare()
{
local list="file1.txt file2.txt file3.txt file4.txt"
rm -f list
touch list
for item in $list
do
echo "hAllo $item" > $item
echo "$item" >> list
done
}
test_prepare
test_do "list"
In this script nano crashes, and I don't know exactly why :-//
-
I suppose nano starts to read your list, interprets it as commands and crashes due to some bug.
Maybe you could save a pointer to the tty file outside the loop and inside the loop redirect nano stdin to the tty.
edit
No need for tty files, just Bash redirects. This errors out
while true; do vi; done </dev/null
but this works
exec 123<&0
while true; do vi <&123; done </dev/null
-
my understanding is that "read" is not a program but rather a "builtin" function to read words, not lines, but "IFS= read -r linea" was introduced later as the canonical way to read one line of input
The used "-r" option should removes the backslash processing, while with the Input Field "IFS="(1) ... "read" should read from stdin one byte at a time until it finds an unescaped newline character or end-of-input, so it doesn't splits a line into words but rather return the whole line.
If it was C code, it would be a kind of
while (!fof(file))
{
get_line(&linea);
}
But it doesn't operate on a file pointer but rather directly on stdin and there is no select() to mitigate so as far as one knows or can see and this is a problem for Nano when it invokes its input methods linked with ncurses to process the stdin.
Redirecting a compound command causes it to run in a subshell ... that's what makes me perplex: in theory, it should work :-//
(1) "IFS=" means empty string, so no character will be used to split, therefore no splitting will occur
-
There is no problem with the loop and with read. They process the "list" file line by line as intended.
The problem is nano. It also runs inside the loop. It also gets the redirect.
It reads commands from the next line of your "list" file instead of the terminal.
You need to save the original stdin descriptor before the loop and pass it to nano.
-
function test_do()
{
local list="$1"
local item
exec 42<&0 #save stdin as filedescriptor 42
while IFS= read -r item
do
nano "$item" <&42 # use filedescritor 42 as stdin
#echo "$item"
done < $list
}
function test_prepare()
{
local list="file1.txt file2.txt file3.txt file4.txt"
rm -f list
touch list
for item in $list
do
echo "hAllo $item" > $item
echo "$item" >> list
done
}
test_prepare
test_do "list"
Yup, this works! Thanks! ;D