在while循环中使用read时遇到多个变量的问题

时间:2015-03-30 21:22:26

标签: bash variables while-loop inotify ifs

还在学习,我迷失了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 <user@domain.com>
CC: Support <user@domain.com>
From: $USER <user@domain.com>
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 list@domain.com
    rm /path/to/temp/file.txt
done

这是我的第一个脚本,只要上传的文件名中没有空格,它就会很好用。我已经阅读了一些使用IFS =&#39;无论什么&#39;定义字段分隔符,但我不想在生产过程中弄乱它;它有效,但当我无法获得上传文件的用户的用户名时,它会让我很烦。请给我一个提示。

1 个答案:

答案 0 :(得分:1)

攻击者可以通过知道您的实现并想要欺骗任意数据(通过使用换行符创建文件名)来解决这个问题,但这是一个粗略的初稿:

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)

我强烈建议使用上游inotifytools提交票证,请求能力在格式字符串中使用\0


顺便提一下,这已经在inotify-tools邮件列表中提出,其中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