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

32

有时候我想对一个文件夹中的所有文件(包括隐藏文件)执行一个命令。当我尝试使用

chmod g+w * .*

这会更改我想要的所有文件(在该目录中)以及父目录中所有文件的权限(我不想更改)。

是否有通配符可以正确处理,还是需要开始使用find命令?

6个回答

45

您需要两个通配符来涵盖所有潜在的“点文件”:.[^.]*..?*

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

chmod g+w .[^.]* ..?*

这个方法在大多数shell中都可以很好地工作,适用于脚本。


对于常规交互使用,这些模式可能太难记了。 对于这些情况,您的shell可能有一种更方便的方法来跳过...zsh总是将....*等模式中排除。 对于bash,您必须使用GLOBIGNORE shell变量。

# bash
GLOBIGNORE=.:..
echo .*

你可以考虑在你的自定义文件(例如.bash_profile/.bash_login.bashrc)中设置GLOBIGNORE。

但是要注意,如果你经常使用其他环境,则不要过于习惯这种自定义设置。如果你在缺少自定义设置的环境中运行像chmod g+w .*这样的命令,那么你将意外地包括...在你的命令中。

此外,你可以配置shell以在不以显式点(例如*)开头的模式中包含“点文件”。

# zsh
setopt glob_dots

# bash
shopt -s dotglob


# show all files, even “dot files”
echo *

6
实际上,那个 GLOBIGNORE 是很不错的。如果你不想永久地更改它,你可以使用 ( GLOBIGNORE=.. ; echo .* ) 来进行临时更改。仅仅因为这一小段信息,我给它加上一个赞。 - paxdiablo
5
使用'.[^.]* ..?*'通配符时,需要注意一个警告信息,除非你设置了shopt nullglob,否则它通常会抱怨..?*部分不匹配。 - pixelbeat

2

通常我只会使用. .[a-zA-Z0-9]*,因为我的文件名往往遵循某些规则,但这不能捕获所有可能的情况。

可以使用:

chmod g+w $(ls -1a | grep -v '^..$')

这段代码基本上会列出所有的文件和目录,剥离掉父级目录后再进行处理。但是要注意文件名中的空格,它会将它们视为单独的文件。

当然,如果你只想处理 文件,可以使用以下代码:

find . -maxdepth 0 -type f -exec chmod g+w {} ';'

或者,另一种解决方案是,可以处理除了..之外的所有文件和目录:
for i in * .* ; do if [[ ${i} != ".." ]] ; then chmod g+w "$i"; fi done

但现在你进入了可能需要脚本或别名的领域。


只需删除 grep -v '^.$',因为 Allan 想要隐藏文件,但不包括父文件夹。 - A.Rashad

2

我所做的是

tar --directory my_directory --file my_directory.tar --create `ls -A mydirectory/`

这个命令ls -A my_directory可以很好的扩展目录,但排除了...。这不需要使用奇怪的通配符,而且输出结果只有一行。

附:也许有人会告诉我为什么这不是一个好主意 :p


没错,它运行得很好(在ls中的“几乎全部”选项),但是为了这样做,您现在正在启动另一个进程,在这种情况下是/bin/ls。通常不是一个坏主意,但是如果您要处理10,000个以上的目录,则可能会占用一些资源。通配符是由shell完成的,不会启动任何进程来生成列表,实际上大多数人只需使用*.[^.]*就可以了,它看起来基本上像一个戴着单片眼镜的秃头男子,所以很容易记住(而且它非常类似于正则表达式,难道现在每个人都知道正则表达式了吗?或者我说得太过分了> :) - osirisgothra
1
如果文件名包含空格,则此方法会失败。 - Ciro Santilli OurBigBook.com

1

这样怎么样:

shopt -s dotglob
chmod g+w ./* 

1

由于您可能不想为 bash 会话的其余部分设置 dotglob,因此您可以通过在子进程中运行来为一组命令设置它,如下所示:

$ (shopt -s dotglob; chmod g+w ./*)

0
如果您确定不会使用两个字符的隐藏文件名,则最简单的选项就是执行以下操作:
chmod g+w * ...*

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接