带有通配符和隐藏文件的 Bash for 循环

问题描述 投票:0回答:6

只是知道一个简单的 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*"

也不起作用。

bash loops scripting wildcard
6个回答
66
投票

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

您可以使用

更改它

shopt -s 点球

$ 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


19
投票

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

#!/bin/bash
shopt -s dotglob
for file in *
do
 echo "$file"
done

11
投票

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

开头

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

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


11
投票

是的,前面的

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

当模式用于路径名扩展时,字符“.” 必须位于名称开头或紧跟在斜杠之后 显式匹配,除非 shell 选项 dotglob 是 放。 匹配路径名时,斜杠字符必须 始终明确匹配。 在其他情况下,“.” 性格没有受到特殊对待。


7
投票

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

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

通配符

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

如果您还有其他带有两个前导点的文件,则需要指定第三个通配符来覆盖这些文件,但排除父目录!尝试

..?*
,它要求第二个点之后至少有一个字符。

如果一个或两个通配符可能不匹配任何文件,您可能需要检查循环内是否没有匹配项。

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

另请注意,您总是希望用文件名引用变量


2
投票
for file in directory/{.[!.]*,*};do echo $file;done

应回显隐藏文件和普通文件。感谢 Tripleee 提供的

.[!.]*
小费。 大括号允许在模式匹配中使用“或”。 {模式1,模式2}

© www.soinside.com 2019 - 2024. All rights reserved.