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

Pet*_*ter 0 linux bash shell echo

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

for i in *.pdf *.sh *.txt;
do
  echo 'all file types with extension' $i;
  find /home/user/pictures -type f -iname $i; 
done
Run Code Online (Sandbox Code Playgroud)

但是当我执行 bash-script 时,对于位于基本目录 /home/user/pictures. 而不是 echo 'All File types with Extension *.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
Run Code Online (Sandbox Code Playgroud)

我想知道为什么 echo - 命令不打印“所有带有扩展名 *.sh 的文件类型”。

ala*_*ani 6

修改后的代码:

for i in '*.pdf' '*.sh' '*.txt'
do
    echo "all file types with extension $i"
    find /home/user/pictures -type f -iname "$i"
done
Run Code Online (Sandbox Code Playgroud)

解释:

在 bash 中,包含 的字符串*或扩展为此类字符串的变量可以扩展为 glob 模式,除非该字符串通过将其放在引号内来防止 glob 扩展(尽管如果 glob 模式不匹配任何文件,则尝试扩展后将保留原始 glob 模式)。

在这种情况下,不希望的膨胀的glob发生-包含字符串*需要为文字到每个被传递echofind命令。所以$i应该用双引号括起来 - 这将允许从 变量扩展$i,但不会发生随后的通配符扩展。(如果使用单引号 ie'$i'代替,那么文字$i将被传递给echo和 to find,这也是不想要的。)

除此之外for,如果当前目录中存在与任何 glob 模式匹配的任何文件,初始行需要使用引号来防止通配符扩展。在这里,使用单引号还是双引号都没有关系。

另外,这里修改后的代码也去掉了一些不必要的分号。bash 中的分号是命令分隔符,不仅仅用于终止语句(如 C 等)。

使用原始代码观察到的行为

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

仍然期望在表达式中使用*.pdfand *.txt- 替换或不替换,取决于是否找到任何匹配项。因此,问题中显示的输出可能不是脚本的整个输出。