Bash:var扩展混乱可能是由于IFS

时间:2018-01-31 23:46:20

标签: bash find whitespace variable-expansion ifs

在阅读getting files with spaces in the name using find之后,我将一个小代码块放在一起,以获取目录中的所有.sh个文件并使其可执行:

find . -type f -name '*.sh' -print0 | 
while IFS= read -r -d '' file; do
  name=$(printf '%s\n' "$file" | sed "s|^\./||")
  echo $name
  if ! [[ -x $name ]] ; then
    chmod +x "${name}"
  fi
done

倒数第三行给了我最大的麻烦。我经历了所有3种排列:

chmod +x $name
chmod +x ${name}
chmod +x "${name}"

我有两个问题:

  1. 我想知道为什么最后一个,只有最后一个,有效。是否与之前设置的IFS位有关?

  2. 如果有更简单的方法可以做到这一点,会是什么?同样,它应该获取当前目录中的所有.sh文件 - 所有文件的文件名都有空格 - 并使它们可执行。

1 个答案:

答案 0 :(得分:0)

当您在命令的开头放置变量赋值时,它仅适用于该命令。因此,您之前设置的IFS仅由read命令使用。其余代码使用默认的IFS,它具有空格作为字段分隔符。

如果您希望将IFS设置应用于所有代码,则需要将其作为单独的语句执行,而不是作为命令的前缀。

IFS=
find . -type f -name '*.sh' -print0 | 
while read -r -d '' file; do
  name=$(printf '%s\n' "$file" | sed "s|^\./||")
  echo $name
  if ! [[ -x $name ]] ; then
    chmod +x "${name}"
  fi
done

但一般来说,你应该引用你的变量。即使设置了IFS,如果变量包含通配符,也会出现问题,因为在展开非引用变量后会扩展通配符。如果你真的需要单词拆分和通配,那么只保留变量不加引号。

相关问题