*是由shell扩展的glob。默认情况下,.除非按.字面意思输入开头,否则外壳程序不包含名称以开头的文件(称为隐藏文件或点文件)。
*或[.]*或?*或*.*或dir/*将不包含点文件。
.*或dir/.*会。
因此,您可以执行以下操作:
mv -- * .* /dest/
但是,某些包含bash(但不包含zsh,mksh也不包含fish)的shell的缺点是扩展了.*include .和..special目录条目,您在这里不需要(并且通常从不希望包含glob,这就是为什么我称其为错误的特性)。
因此,您会发现有时人们会使用(在类似Bourne的贝壳中):
mv -- * .[!.]* ..?* /dest/
这是三个glob,第一个匹配非隐藏文件,第二个.以不以其他字符.开头的文件名,第三个..以不以其他字符开头的文件名。
但是,一些现代的外壳具有更好的解决方案
sh
使用zsh,您可以使用(D)glob限定符来指定glob应该包含点文件:
mv -- *(D) /dest/
zsh还修复了Bourne shell的其他功能缺陷,即如果模式不匹配,则mv命令不会运行。
如上文所述,它也永远不会包含.也不会包含..在其全局范围内,因此
mv -- * .* /dest/
会很安全。但是,如果没有文件匹配*或没有文件匹配,.*该命令将被中止,因此最好使用:
mv -- (*|.*) /dest/
像在其他shell中一样,您还可以强制所有glob包含点文件(例如,如果您发现自己想要的点文件经常被包括):
setopt dotglob
要么:
set -o dotglob
之后,如果您希望特定的glob 不包含点文件,则可以编写它:
echo *(^D)
要么:
echo [^.]*
重击
不幸的bash是没有glob限定词。因此,您只需要全局启用点文件包含即可。在中bash,语法为:
shopt -s dotglob
(并[^.]*用于没有隐藏文件的全局文件)。
使用dotglob,bash不包含.也不包含..在全局变量中*,但仍然适用于全局变量.*。
如果将GLOBIGNORE变量设置为非空值,则它将自动启用该dotglob选项,.并..从.*glob中排除and ,但不从dir/.*or中排除.*/file(!),因此保护措施几乎毫无用处。您可以这样做,GLOBIGNORE='*/.:*/..:./*:../*:*/./*:*/../*'但是那样会破坏glob */.或./*or或glob ../*。
更好的解决方法是使用[.]*或dir/[.]*或[.]*/file(dotglob启用)来扩展点文件(.和除外)..。
鱼
fish全局不包含.也不..。如果没有匹配项,则取决于版本,它将像zsh(或bash -o failglob)或一样工作bash -o nullglob。
mv -- * .* /dest/
如果同时存在隐藏文件和非隐藏文件,则可以使用。否则,mv -- /dest如果没有任何文件,则可能会调用YMMV以及某些版本的文件。
ksh93
ksh93两者中都没有glob限定词。您可以通过以下方式在全球范围内包含点文件:
FIGNORE='@(.|..)'
相反bash的GLOBIGNORE,这是正确完成,也解决的问题.*,包括.和..。
ash
yash有一个dot-glob选项(set -o dot-glob),但与相反bash,全局扩展(甚至是*)包含在内.,..因此它毫无用处。
tcsh
set globdot
类似于中的工作bash,即*包含点文件(.和),..但.*仍然包括.和..(并且您可以[.]*用来扩展隐藏文件(.和..)。