-1

I want to update a global variable "VARIABLE" within a while loop. As far I understand from other questions, I need to change my code in such a way that while loop is not a separate subprocess. To make it happen, I changed:

VARIABLE=1

/usr/bin/inotifywait --monitor --quiet -e moved_to -e close_write --format '%w%f' "$CACHE_DIR" | while read -r INPUT_FILE
do
VARIABLE=42
done

to:

VARIABLE=1

while read -r INPUT_FILE
do
VARIABLE=42
done <<< "$(/usr/bin/inotifywait --monitor --quiet -e moved_to -e close_write --format '%w%f' "$CACHE_DIR")"

However, it seems that now inotifywait never notifies about events, but it worked fine before. What is wrong? If for whatever reason my approach is not suitable for inotifywait, are there any alternatives?

Starid
  • 31
  • 6
  • 2
    Avoid using a here string, but use `while ...done < <(command)` – kvantour Jun 19 '21 at 07:53
  • Thanks @kvantour, I confirm that it solves the problem. Apparently I cannot mark problem as solved for two days :( – Starid Jun 19 '21 at 08:01
  • 1
    `I want to update a global variable "VARIABLE" within a while loop.` what for? `however, global VARIABLE is not updated` How do you check that? – KamilCuk Jun 19 '21 at 08:06
  • I vote to re-open this question. The question does not address the local shell in a pipe-line issue, but address the differences between a here-string from a subshell and input-redirection from process substitution. The OP did his research and knew how to tackle the local shell problem (by removing the pipe) but opened a new can of worm(s). The question could be closed if it is linked to a question that addresses the difference between a here-string obtained from a subshell (`<<< $(command)`) or input-redirection combined with process-substitution. – kvantour Jun 20 '21 at 09:07
  • Related: [U&L: Why is a here-string command substitution considered as a single line?](https://unix.stackexchange.com/questions/164110) – kvantour Jun 20 '21 at 09:13

2 Answers2

1

As @kvantour described in a comment, it should be

done < <(/usr/bin/inotifywait --monitor --quiet -e moved_to -e close_write --format '%w%f' "$CACHE_DIR")

not

done <<< "$(/usr/bin/inotifywait --monitor --quiet -e moved_to -e close_write --format '%w%f' "$CACHE_DIR")"
Starid
  • 31
  • 6
  • 3
    The critical difference is that `$( )` *waits for the command inside to finish*, then converts its output into a string. After that's finished (which never actually happens), the main loop runs and `<<<` passes that string as input to it `< <( )`, on the other hand, runs both commands at once, with output from the one in `<( )` passing to the other *as it's produced*. – Gordon Davisson Jun 19 '21 at 08:29
1

What is wrong?

Command substitution $(...) waits until the command completes and grabs the output of the command and substitutes the $(...) for the output. Because inotifywait does not exit, your shell just waits... infinitely.

If for whatever reason my approach is not suitable for inotifywait, are there any alternatives?

See https://mywiki.wooledge.org/BashFAQ/024 . Using process substitution with a redirection < <(...) is typically used in scripts when you want to preserve the environment from a loop. You seem to want to implement some interprocess communication using a global variable - I believe would advise using fifos or files instead. Using global variables smells of spaghetti.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111