Author Topic: [solved] Bash: why does nano crash within a "while IFS= read{}" loop?  (Read 1248 times)

0 Members and 1 Guest are viewing this topic.

Online DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3894
  • Country: gb
Code: [Select]
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 :-//
« Last Edit: October 09, 2021, 08:07:55 pm by DiTBho »
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online magic

  • Super Contributor
  • ***
  • Posts: 6747
  • Country: pl
Re: Bash: why nano does crash within a "while IFS= read{}" loop?
« Reply #1 on: October 09, 2021, 05:37:38 pm »
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: [Select]
while true; do vi; done </dev/nullbut this works
Code: [Select]
exec 123<&0
while true; do vi <&123; done </dev/null
« Last Edit: October 09, 2021, 05:43:16 pm by magic »
 
The following users thanked this post: DiTBho

Online DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3894
  • Country: gb
Re: Bash: why does nano crash within a "while IFS= read{}" loop?
« Reply #2 on: October 09, 2021, 07:09:51 pm »
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: [Select]
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
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 

Online magic

  • Super Contributor
  • ***
  • Posts: 6747
  • Country: pl
Re: Bash: why does nano crash within a "while IFS= read{}" loop?
« Reply #3 on: October 09, 2021, 07:52:25 pm »
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.
 

Online DiTBhoTopic starter

  • Super Contributor
  • ***
  • Posts: 3894
  • Country: gb
Re: Bash: why does nano crash within a "while IFS= read{}" loop?
« Reply #4 on: October 09, 2021, 08:07:32 pm »
Code: [Select]
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
The opposite of courage is not cowardice, it is conformity. Even a dead fish can go with the flow
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf