如何在bash中使用.*通配符但排除父目录(..)?

All*_*lan 30 bash wildcard

有时候我想对目录中的所有文件(包括隐藏文件)执行命令.当我尝试使用时

chmod g+w * .*
Run Code Online (Sandbox Code Playgroud)

它更改了我想要的所有文件(在目录中)和父目录中的所有文件(我想要单独留下)的权限.

是否有正确的通配符,或者我是否需要开始使用find?

Chr*_*sen 40

你需要两个glob模式来覆盖所有潜在的"点文件":.[^.]*..?*.

第一个匹配具有两个或多个字符的所有目录条目,其中第一个字符是点,第二个字符不是点.第二个选择带有三个或更多字符开头的条目..(这个排除..因为它只有两个字符并以a开头.,但包括(不太可能)条目..foo).

chmod g+w .[^.]* ..?*
Run Code Online (Sandbox Code Playgroud)

这应该适用于大多数所有shell,适用于脚本.


对于常规交互式使用,模式可能难以记住.对于这些情况,你的shell可能有一个更方便的方法跳过.... zsh总是排除...模式之类的.*.使用bash,您必须使用GLOBIGNORE shell变量.

# bash
GLOBIGNORE=.:..
echo .*
Run Code Online (Sandbox Code Playgroud)

您可以考虑在其中一个bash自定义文件中设置GLOBIGNORE (例如.bash_profile/ .bash_login.bashrc).但是,如果您经常使用其他环境,请注意习惯这种自定义.如果您chmod g+w .*在缺少自定义的环境中运行命令,那么您将意外地结束包含...在命令中.

此外,您可以将shell配置为在不以明确点(例如*)开头的模式中包含"点文件" .

# zsh
setopt glob_dots

# bash
shopt -s dotglob


# show all files, even “dot files”
echo *
Run Code Online (Sandbox Code Playgroud)

  • 实际上,GLOBIGNORE是一个很好的.你可以用`(GLOBIGNORE = ..; echo.*)`暂时执行它,如果你不想让它永久化的话.单独为这一小段信息+1. (6认同)
  • 有一个警告,'.[^.]*..?*'glob通常会抱怨..?*部分不匹配,除非你购买nullglob. (5认同)