4

I have a global variable $EMAIL. I want to loop through several files and for each that meets a criteria I will add it to $EMAIL for report generation.

The problem is when I redefine $EMAIL inside the loop it only changes $EMAIL at the scope of the loop iteration. The global version of $EMAIL remains empty.

This is a simplified version of my program:

#!/usr/bin/env bash

EMAIL="I echo without 'nope'"
ls | while read line; do
  if [ 73523 -lt 86400 ]
  then
    echo "Hasn't been backed up in over a day"
    EMAIL="$EMAIL nope"
  fi
done

echo $EMAIL

How can I modify my script so that I can add to $EMAIL from inside the loop?


Edit/Update

I wanted to further simplify the example so I tried changing

ls | while read line; do

to:

for i in {1..2}; do

Strangely with this change nope is appended to $EMAIL, maybe I'm misunderstanding what is going wrong here?

2 Answers2

10

In:

cmd1 | cmd2

bash run cmd2 in a subshell, so changing variable won't be visible to parent shell.

You can do:

#!/usr/bin/env bash

EMAIL="I echo without 'nope'"
while read line; do
  if [ 73523 -lt 86400 ]
  then
    echo "Hasn't been backed up in over a day"
    EMAIL="$EMAIL nope"
  fi
done < <(ls)

echo "$EMAIL"

or using zsh or ksh, which will run cmd2 in the same shell process.

cuonglm
  • 153,898
3

@cuonglm has the answer to your question. However your problem is parsing the output of ls. You should do this:

email="..."
for file in *; do
    t=$(calculate_last_backup "$file")
    if some_condition_with "$t"; then
        email+="some text"
    fi
done
do_something_with "$email"
glenn jackman
  • 85,964