有时候我想对一个文件夹中的所有文件(包括隐藏文件)执行一个命令。当我尝试使用
chmod g+w * .*
这会更改我想要的所有文件(在该目录中)以及父目录中所有文件的权限(我不想更改)。
是否有通配符可以正确处理,还是需要开始使用find命令?
您需要两个通配符来涵盖所有潜在的“点文件”:.[^.]*
和 ..?*
。
第一个匹配所有具有两个或更多字符的目录条目,其中第一个字符是点,第二个字符不是点。第二个选取以..
开头且具有三个或更多字符的条目(这将排除..
,因为它只有两个字符并以.
开头,但包括(不太可能的)条目,如..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 *
通常我只会使用. .[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
但现在你进入了可能需要脚本或别名的领域。
我所做的是
tar --directory my_directory --file my_directory.tar --create `ls -A mydirectory/`
这个命令ls -A my_directory
可以很好的扩展目录,但排除了.
和..
。这不需要使用奇怪的通配符,而且输出结果只有一行。
附:也许有人会告诉我为什么这不是一个好主意 :p
这样怎么样:
shopt -s dotglob
chmod g+w ./*
由于您可能不想为 bash 会话的其余部分设置 dotglob,因此您可以通过在子进程中运行来为一组命令设置它,如下所示:
$ (shopt -s dotglob; chmod g+w ./*)
chmod g+w * ...*
( GLOBIGNORE=.. ; echo .* )
来进行临时更改。仅仅因为这一小段信息,我给它加上一个赞。 - paxdiablo