【问题标题】:Having trouble with multiple variables using read in a while loop在 while 循环中使用 read 处理多个变量时遇到问题
【发布时间】:2015-06-04 01:53:38
【问题描述】:

仍在学习,我迷失了 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= 'whatever' 来定义字段分隔符的脚本,但我不想在生产时搞乱它;它可以工作,但是当我无法获取上传文件的用户的用户名时,这让我很恼火。请给我一个提示。

【问题讨论】:

  • 由于 inotifywait 的格式字符串不支持 \0 - 文件名中唯一不能合法存在的字符 - 实际上 isn't 是 100% - 可靠的解决方案。
  • @CharlesDuffy 这就是我害怕的...
  • 顺便说一句,注意我是如何在 "$file" 或 "$path" 的任何扩展周围使用双引号的?这对于避免错误至关重要; shellcheck.net 会指出你跳过的任何地方。
  • 顺便说一句,您确定要create(在创建文件时进行标记,但不一定在向其写入内容完成时),而不是@ 987654328@?

标签: bash variables while-loop inotify ifs


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-02
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 2020-05-14
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多