Bash: 变量扩展混乱可能是由于 IFS
Bash: var expansion confusion possibly due to 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}"
我有两个问题:
我想知道为什么最后一个,而且只有最后一个,有效。跟之前设置的IFS
位有关系吗?
如果有更简单的方法来做到这一点,那会是什么?同样,它应该抓取当前目录中的所有 .sh
个文件——所有这些文件的文件名中都有空格——并使它们可执行。
当您将变量赋值放在命令的开头时,它仅适用于该命令。所以你之前设置的 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
,如果变量中包含通配符也会有问题,因为通配符是在展开非引号变量后展开的。如果您确实需要分词和通配,则只保留变量不加引号。
阅读 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}"
我有两个问题:
我想知道为什么最后一个,而且只有最后一个,有效。跟之前设置的
IFS
位有关系吗?如果有更简单的方法来做到这一点,那会是什么?同样,它应该抓取当前目录中的所有
.sh
个文件——所有这些文件的文件名中都有空格——并使它们可执行。
当您将变量赋值放在命令的开头时,它仅适用于该命令。所以你之前设置的 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
,如果变量中包含通配符也会有问题,因为通配符是在展开非引号变量后展开的。如果您确实需要分词和通配,则只保留变量不加引号。