*
是由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
,即*
包含点文件(.
和),..
但.*
仍然包括.
和..
(并且您可以[.]*
用来扩展隐藏文件(.
和..
)。