snowexcuse
snowexcuse

Reputation: 3

Having trouble with multiple variables using read in a while loop

Still learning and I'm getting lost with IFS=

#!/bin/bash
inotifywait -m -r --excludei '(.txt$|.old$|.swp$|.swx$|.swpx$|.zip$)' /path/to/watch -e create |
    while read path action file; do
        cd $path
        USER="$(stat -c %U $file)"
        echo "To: User <[email protected]>
CC: Support <[email protected]>
From: $USER <[email protected]>
Subject: $USER has Uploaded a new File

The user '$USER' uploaded the file '$file' to '$path'" >  /mnt/remote/ian/temp2.txt
    cat /path/to/temp/file.txt | ssmtp [email protected]
    rm /path/to/temp/file.txt
done

This was my first ever script and it works great as long as there are no spaces in the the file names that get uploaded. I've read some scripts that use IFS= 'whatever' to define the field separators but I don't want to mess around with this while it's in production; it works, but it annoys me when I can't get the username of the user who uploaded the file. Please give me a hint.

Upvotes: 0

Views: 257

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295281

This can be broken by an attacker who knows your implementation and wants to spoof arbitrary data (by creating filenames with newlines), but it's a rough first draft:

while IFS= read -r -d $'\n' path && IFS= read -r -d $'\n' file; do
    user=$(stat -c %U "$file")
    printf 'File %q created by %q in %q\n' "$file" "$user" "$path"
done < <(inotifywait --format $'%w\n%f\n' ~/tmp -r -e create)

I'd strongly suggest filing a ticket with upstream inotifytools requesting the ability use \0 in format strings.


Incidentally, this has already been brought up on the inotify-tools mailing list, where Stephane Chazelas offered a workaround:

nl="
"
inotifywait --syslog -e close_write -mr /tmp --format '%f///' |
  while IFS= read -r file; do
    while :; do
      case $file in
        (*///) file=${file%///}; break
      esac
      IFS= read -r extra || exit
      file=$file$nl$extra
    done

    something with "$file"

  done

Upvotes: 1

Related Questions