为什么 bash 数组的一部分作为命令执行?
Why is part of a bash array is executed as a command?
示例 运行 Raspberry Pi 3 运行ning 2017-04-10 版本的 Raspbian Jessie 已更新至 2017 年 6 月上旬。Bash 的版本是 4.3.30(1)。
最近在尝试一些代码时,我发现正在执行 bash 数组的内容。幸运的是他们并不危险!
这是一个简单的函数:
#!/bin/bash
echo "y.sh starting"
echo "parameter string is <$@>"
args=( $@ )
echo "args array is <${args[@]}>"
echo "args array length is ${#args[@]}"
echo "y.sh ending"
这是输出
pi@brassica:~ $ ./y.sh
y.sh starting
parameter string is <>
args array is <>
args array length is 0
y.sh ending
pi@brassica:~ $ ./y.sh ls
y.sh starting
parameter string is <ls>
args array is <ls>
args array length is 1
y.sh ending
上面没有意外。
加入y*参数后,ls命令输出数组中出现:
pi@brassica:~ $ ./y.sh ls y*
y.sh starting
parameter string is <ls y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array is <ls y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array length is 8
y.sh ending
但是加上-la后,就没有额外信息的迹象了
pi@brassica:~ $ ./y.sh ls -la y*
y.sh starting
parameter string is <ls -la y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array is <ls -la y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array length is 9
y.sh ending
如果有人能解释执行命令的原因以及可以进行哪些更改以使其不被执行,那将非常有帮助。对为什么不产生 ls 的 "long" 输出的解释也很有趣。
来自柴郡猫之家的感谢。
您没有执行 ls -la y*
您正在向 y.sh
传递参数。第一个是 ls
,然后是 -la
然后 glob y*
扩展到的所有文件都成为它自己的参数。
所以你没有执行命令,但是 glob 正在被 shell 扩展。
当你 运行 ls y*
时也会发生这种情况。您实际上并没有将字符串 y*
传递给 ls
。相反,shell 扩展了 y*
并将每个与 glob 匹配的文件作为 ls
的参数放置,所以你真的 运行ning
ls y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq
当您输入时
ls y*
您也可以使用其他命令看到相同的效果。例如,echo
将打印给定的每个参数,因此您可以通过执行 echo y*
来模拟 ls y*
(尽管 echo 不会显示任何以 y 开头的目录的内容)
示例 运行 Raspberry Pi 3 运行ning 2017-04-10 版本的 Raspbian Jessie 已更新至 2017 年 6 月上旬。Bash 的版本是 4.3.30(1)。
最近在尝试一些代码时,我发现正在执行 bash 数组的内容。幸运的是他们并不危险!
这是一个简单的函数:
#!/bin/bash
echo "y.sh starting"
echo "parameter string is <$@>"
args=( $@ )
echo "args array is <${args[@]}>"
echo "args array length is ${#args[@]}"
echo "y.sh ending"
这是输出
pi@brassica:~ $ ./y.sh
y.sh starting
parameter string is <>
args array is <>
args array length is 0
y.sh ending
pi@brassica:~ $ ./y.sh ls
y.sh starting
parameter string is <ls>
args array is <ls>
args array length is 1
y.sh ending
上面没有意外。
加入y*参数后,ls命令输出数组中出现:
pi@brassica:~ $ ./y.sh ls y*
y.sh starting
parameter string is <ls y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array is <ls y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array length is 8
y.sh ending
但是加上-la后,就没有额外信息的迹象了
pi@brassica:~ $ ./y.sh ls -la y*
y.sh starting
parameter string is <ls -la y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array is <ls -la y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq>
args array length is 9
y.sh ending
如果有人能解释执行命令的原因以及可以进行哪些更改以使其不被执行,那将非常有帮助。对为什么不产生 ls 的 "long" 输出的解释也很有趣。
来自柴郡猫之家的感谢。
您没有执行 ls -la y*
您正在向 y.sh
传递参数。第一个是 ls
,然后是 -la
然后 glob y*
扩展到的所有文件都成为它自己的参数。
所以你没有执行命令,但是 glob 正在被 shell 扩展。
当你 运行 ls y*
时也会发生这种情况。您实际上并没有将字符串 y*
传递给 ls
。相反,shell 扩展了 y*
并将每个与 glob 匹配的文件作为 ls
的参数放置,所以你真的 运行ning
ls y01.sh y02.sh y03.sh y04a.sh y04.sh y.sh ytq
当您输入时
ls y*
您也可以使用其他命令看到相同的效果。例如,echo
将打印给定的每个参数,因此您可以通过执行 echo y*
来模拟 ls y*
(尽管 echo 不会显示任何以 y 开头的目录的内容)