问题描述
我将我的主目录从旧系统迁移到新目录,并且我制作的tarball包含了所有内容,包括像.bashrc之类的隐藏文件。但是,当我将解压缩的tarball(位于/tmp)中的内容移动到我的新主目录时,隐藏文件不会复制(mv /tmp/home/rcook/* /home/rcook/
)。我怎样才能让mv移动它们?
其实,我认为问题不在于mv,而在于bash的通配。如果我这样做:
mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/
我看到这个:
a/:
. .. .foo
b/:
. .. bar
a/.foo
没有移动。那么我怎样才能获得*通配符来查找隐藏的文件呢?
是的,我想我可以直接将压缩包解压缩到我的主目录中,但tarball解压缩为home/rcook/...
,我想确保使用旧的定制版本覆盖新的.bashrc
等,并知道如何查找和移动隐藏文件是一项有价值的技能。建议?
一些答案建议做类似mv src/.* dest/
的事情。但是,我在我的测试目录中尝试了这一点,并得到错误。从…开始:
rcook$ ls -a a/ b/
a/:
. .. bar .foo
b/:
. ..
rcook$ mv a/.* b/
mv: cannot move 'a/.' to 'b/.': Device or resource busy
mv: cannot remove 'a/..': Is a directory
rcook$ ls -a a/ b/
a/:
. .. bar
b/:
. .. .foo
我究竟做错了什么?
最佳解决思路
你可以这样做 :
shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/
你可以放
shopt -s dotglob
在您的~/.bashrc
中,如果您希望它成为默认值。
参见http://mywiki.wooledge.org/glob
复制点文件的另一种方法是:
mv /tmp/home/rcook/.[!.]* /home/rcook/
不要使用..*
模式,因为它与..
(指向父目录的指针)相匹配。如果有名称以两个点开头的文件(..something
),也可以使用..?*
格式。
次佳解决思路
在你的补充,你有错误,但代码仍然工作。唯一要补充的是,你告诉它只复制点文件。尝试:
mv src/* src/.* dst/
你仍然会得到错误。和..条目,这很好。但此举应成功。
~/scratch [andrew] $ mv from/* from/.* to/
mv: cannot move ‘from/.’ to ‘to/.’: Device or resource busy
mv: cannot remove ‘from/..’: Is a directory
~/scratch [andrew] $ ls -a from/ to/
from/:
. ..
to/:
. .. test .test
第三种解决思路
如果您在目录中使用ls -l
,则会在列出的文件中看到.
和..
。所以,我认为mv .* /dest
将这些指标考虑在内。尝试:
mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/
这会忽略当前和父目录指针。
如果*
,[^.]*
或..?*
三种模式中的任何一种与任何文件都不匹配,您将收到错误,因此您应该只包含匹配的文件。
第四种思路
我能想到两种可能的解决方案。首先是使用cp而不是递归选项,将当前目录复制到目标。
cp -Rp . /desired/directory
那么你可以删除当前目录中的源文件
另外,如果你知道这些文件是明确命名的(没有空格,通配符,non-printable字符),你可以做这样的事情
mv $(ls -A) /desired/directory
第五种思路
Linux上没有”hidden”文件。默认情况下,以点开头的文件只会隐藏文件列表。
要使用glob复制文件,需要在文件前加上.
(如mv -u .* foo
),然后.foo
将在移动时显示为foo/.foo
。
-u选项只会在源文件较新或目标文件丢失时移动文件。或者你可以忽略关于移动.
和..
的错误,因为它们是特殊文件,无法移动,但会被shell中的.*
glob捕获。