Linux 为什么echo命令解释基本目录的变量?

Linux 为什么echo命令解释基本目录的变量?,linux,bash,shell,echo,Linux,Bash,Shell,Echo,我想在pictures文件夹中找到一些文件类型,我在/home/user/pictures文件夹中创建了以下bash脚本: for i in *.pdf *.sh *.txt; do echo 'all file types with extension' $i; find /home/user/pictures -type f -iname $i; done 但是,当我执行bash脚本时,对于位于基本目录/home/user/pictures上的文件,它不会像预期的那样工作。命令解

我想在pictures文件夹中找到一些文件类型,我在
/home/user/pictures
文件夹中创建了以下bash脚本:

for i in *.pdf *.sh *.txt;
do
  echo 'all file types with extension' $i;
  find /home/user/pictures -type f -iname $i; 
done
但是,当我执行bash脚本时,对于位于基本目录
/home/user/pictures
上的文件,它不会像预期的那样工作。命令解释基本目录的变量,而不是echo“扩展名为*.sh的所有文件类型”:

all file types with extension file1.sh
/home/user/pictures/file1.sh
all file types with extension file2.sh
/home/user/pictures/file2.sh
all file types with extension file3.sh
/home/user/pictures/file3.sh
我想知道为什么echo-command不打印“扩展名为*.sh的所有文件类型”

此类表达式(*.blabla)更改循环中
$i
的值。下面是我要做的技巧:

pdf sh txt中的i的
;
做
echo“扩展名为*.i的所有文件类型”;
find/home/user/pictures-type f-iname'*.'$i;
完成
修订代码: 说明: 在bash中,包含
*
的字符串或扩展为此类字符串的变量可以扩展为全局模式,除非该字符串通过将其放在引号中以防止全局扩展(尽管如果全局模式与任何文件不匹配,则在尝试扩展后原始全局模式将保持不变)

在这种情况下,不希望发生全局扩展-需要将包含
*
的字符串作为文本传递给每个
echo
find
命令。因此,
$i
应该用双引号括起来-这将允许从
$i
展开变量,但不会发生后续的通配符展开。(如果改为使用单引号,即
'$i'
,则文本
$i
将被传递到
echo
find
,这也是不需要的。)

除此之外,如果当前目录中存在与任何glob模式匹配的任何文件,则的初始行需要使用引号来防止通配符扩展。在这里,使用单引号或双引号并不重要

另外,这里的修订代码还删除了一些不必要的分号。bash中的分号是一个命令分隔符,不仅仅用于终止语句(如C等)

使用原始代码观察到的行为 这里似乎发生的事情是,在初始的
for
语句中使用的模式之一是匹配当前目录中的文件(特别是
*.sh
匹配
file1.sh
file2.sh
file3.sh
)。因此,它将被表达式中这些文件名的列表(
file1.sh file2.sh file3.sh
)替换,并且
for
语句将迭代这些值。(请注意,当前目录可能与脚本所在的目录或用于
查找的顶级目录不同。)


还可以预期表达式中会使用
*.pdf
*.txt
——替换或不替换,这取决于是否找到匹配项。因此,问题中显示的输出可能不是脚本的全部输出。

因为$i更改为文件名而不是扩展名,所以您使用了glob(*)字符,shell查找所有.sh文件。也就是说,
*.pdf
在循环开始迭代之前扩展为pdf文件列表
i
未设置为字符串
*.pdf
。非常感谢您的详细解释。我已经采纳了你的修订,现在脚本按预期运行。☺️您仍然可以在不展开glob的情况下正确引用扩展:
-iname“*.$i”
for i in '*.pdf' '*.sh' '*.txt'
do
    echo "all file types with extension $i"
    find /home/user/pictures -type f -iname "$i"
done