Computing > Programming

[solved] Bash: why does nano crash within a "while IFS= read{}" loop?

(1/1)

DiTBho:

--- Code: ---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"

--- End code ---

In this script nano crashes, and I don't know exactly why :-//

magic:
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

--- Code: ---while true; do vi; done </dev/null
--- End code ---
but this works

--- Code: ---exec 123<&0
while true; do vi <&123; done </dev/null
--- End code ---

DiTBho:
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

--- Code: ---while (!fof(file))
{
    get_line(&linea);
}

--- End code ---

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

magic:
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.

DiTBho:

--- Code: ---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"

--- End code ---

Yup, this works! Thanks!  ;D

Navigation

[0] Message Index

There was an error while thanking
Thanking...
Go to full version