29

只知道一个简单的 shell 脚本,有点困惑:

这是我的脚本:

% for f in $FILES; do echo "Processing $f file.."; done

命令:

ls -la | grep bash 

产生:

% ls -a | grep bash
.bash_from_cshrc
.bash_history
.bash_profile
.bashrc

什么时候

FILES=".bash*"

我得到与 ls -a 相同的结果(不同的格式)。然而当

FILES="*bash*"

我得到这个输出:

Processing *bash* file..

这不是预期的输出,也不是我所期望的。我不能在文件名的开头使用通配符吗?是个 。在文件名“特殊”的开头不知何故?

环境

FILES="bash*"

也不起作用。

4

5 回答 5

58

bash 中的默认通配符不包括以 . (又名隐藏文件)。

你可以改变它

shopt -s dotglob

$ ls -a
.  ..  .a  .b  .c  d  e  f
$ ls *
d  e  f
$ shopt -s dotglob
$ ls *
.a  .b  .c  d  e  f
$ 

要再次禁用它,请运行shopt -u dotglob.

于 2010-01-25T21:39:05.983 回答
15

如果要隐藏和非隐藏,请设置 dotglob (bash)

#!/bin/bash
shopt -s dotglob
for file in *
do
 echo "$file"
done
于 2010-01-26T00:19:19.827 回答
11

FILES=".bash*"有效,因为隐藏文件名以.

FILES="bash*"不起作用,因为隐藏文件名以 a 开头,.而不是 ab

FILES="*bash*"不起作用,因为*字符串开头的通配符省略了隐藏文件。

于 2010-01-25T21:32:51.893 回答
11

是的,.前面的 是特殊的,通常不会与*通配符匹配,如 bash 手册页中所述(并且对于大多数 Unix shell 来说很常见):

当模式用于路径名扩展时,字符“.” 除非设置了 shell 选项dotglob,否则必须显式匹配名称开头或斜线之后的紧随其后的 位置。匹配路径名时,斜杠字符必须始终显式匹配。在其他情况下,“。” 字符没有特殊处理。

于 2010-01-25T21:36:24.913 回答
1

如果要包含隐藏文件,可以指定两个通配符;一个用于隐藏文件,另一个用于其他文件。

for f in .[!.]* *; do
    echo "Processing $f file.."
done

通配符.*将扩展到所有点文件,但包括父目录,您通常希望将其排除在外;所以.[!.]*匹配所有第一个字符是点的文件,但第二个不是。

如果您有其他带有两个前导点的文件,则需要指定第三个通配符来覆盖这些文件,但不包括父目录!试试..?*这要求在第二个点之后至少有一个字符。

于 2021-05-20T07:51:45.050 回答