如何获得MV(或*通配符)来移动隐藏文件?


133

我正在将主目录从旧系统迁移到新系统,我制作的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直接解压缩到主目录中,但是将tarball解压缩到home/rcook/...,并且我想确保我.bashrc用旧的自定义版本覆盖了new 等,并且知道如何查找和移动隐藏文件是一项值得的技能。有什么建议吗?


一些答案建议您做类似的事情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

我究竟做错了什么?


Answers:


146

你可以这样做 :

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)开头,则也使用模式..?*


请查看我在问题底部添加的内容。谢谢。
兰德尔·库克

1
没有任何事情错了,.而且..是特价迪尔斯:分别为当前目录父目录。这只是一个警告。更好地使用shopt -s dotglob解决方案
Gilles Quenot 2013年

我最后只做了两个动作:mv home/rcook/* /home/rcook/跟着mv home/rcook/.* /home/rcook/。尽管我希望我跟随该链接并首先阅读有关dotglob模式的知识,但这确实可以解决问题。这样可以节省我一步。+1
Randall Cook

那么第二种方法需要使用绝对路径吗?
franzlorenzon 2013年

3
如果你使用zsh,你可以使用D通配符预选赛GLOB_DOTS外壳选项
mgalgs 2014年

43

在添加的内容中,您遇到了错误,但是代码仍然有效。唯一要添加的是您告诉它复制点文件。尝试:

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

1
好点,@ AndrewSchwartz。我也喜欢这种方法。我认为这值得更多的认可。
兰德尔·库克

我喜欢@Drake Clarris回答更多,因为我正在Amazon AWS CodeBuild上运行,并且非零返回码实际上导致构建停止。我最终移动了一个.hidden我明确要解决的文件。
HeyWatch今年

如果非零退出代码是一个问题,则可以将其抑制,例如,通过追加|| :||表示对false / error执行以下:操作,是noop命令)。但这也将抑制合法错误,例如目标文件夹不存在。我找不到mv用于排除...条目的更优雅的方式。通过cp对我来说最大的好处是不会将新文件写入磁盘。
安德鲁·施瓦兹

10

如果您ls -l在目录中,则将在列出的文件中看到...。因此,我认为mv .* /dest考虑了这些指针。尝试:

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/

这将忽略那些当前和父目录指针。

如果有三种模式,你会得到一个错误*[^.]*或者..?*没有文件相匹配,所以你应该只包含匹配的人。


真好 对于这种类型的globing,类似的答案在这里:superuser.com/a/784046/144977。感谢您发布此信息。
phyatt

7

我可以想到两种可能的解决方案。第一种是将cp与其递归选项一起使用,将当前目录复制到目标位置。

cp -Rp . /desired/directory

然后您可以删除当前目录中的源文件

另外,如果您知道文件的名称是明智的(没有空格,通配符,不可打印的字符),则可以执行以下操作

mv $(ls -A) /desired/directory

4
如果源和目标位于同一文件系统上,则复制然后删除与移动有很大不同。至少包括-p保留元数据的选项。使用ls应该是万不得已的方法,这里有更好,更简单的方法。
Gilles 2014年

2

在Linux上,实际上并没有所谓的“隐藏”文件。默认情况下,仅从文件列表中隐藏以点开头的文件。

要复制文件(甚至带有glob),您需要在文件.前面加上诸如mv -u .* foo,然后在移动时.foo将显示为foo/.foo

-u选项仅在源较新或目标丢失时才移动文件。或者,您可以忽略有关移动的错误...因为它们是特殊文件,无法移动,但确实会被.*外壳卡住。


请查看我在问题底部添加的内容。谢谢。
兰德尔·库克

0

因此,我们有:

a
|-- .foo
`-- bar

和:

b

我花了很多时间来找到比这里的所有答案更好的解决方案。

然后我花了30秒执行以下命令:

$ mv --help

然后我找到了我的爱人:

$ mv a/ b/ -T

注意:我什至不理解该论点-T。它满足了我的需要。它说:

-T,--no-target-directory 将DEST视为普通文件


1
如果省略斜线,则不需要-T。无论哪种方式,这实际上都是在告诉mv移动目录本身,而不是从目录内部移动所有文件。
thomasrutter 2015年

@thomasrutter,移动目录本身与重命名目录不一样吗?
兰德尔·库克

3
是的,如果父目的地保持不变,则实际上只是重命名了。无论您引用它是什么,它都可能无助于回答原始问题,该问题是将目录的文件移动到给定位置。
thomasrutter 2015年

0

在我的情况下,我只是尝试访问mv一个隐藏文件,这是解决方案:

FILE=.myHiddenFile
mv "$FILE" dest/

说明

起初我在尝试:

mv .myHiddenFile dest/

但是它不断产生错误:

mv: cannot stat '.myHiddenFile': No such file or directory

即使ls -al显示文件和dest/存在。

原因似乎是因为外壳程序正在解释“。”。在文件名中,因此将其移至变量可以避免解释。可能还有其他方法可以解决此问题,但这对我们来说已经足够。


-1

如果要将包含隐藏文件的文件复制到您所在的当前目录中。

cp -Rp source-directory/. .

1
这与Drake Clarris在2013年的回答非常相似。您还有其他要补充的内容吗?
兰德尔·库克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.