我正在将主目录从旧系统迁移到新系统,并且我制作的tarball包含了所有内容,包括.bashrc之类的隐藏文件。但是,当我将解压缩的tarball的内容(位于/ tmp中)移动到新的主目录中时,隐藏的文件不会被复制(mv /tmp/home/rcook/* /home/rcook/)。

实际上,我认为问题不在于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等,并且知道如何查找和移动隐藏文件是一项值得的技能。有建议吗?


一些答案​​建议做类似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


我在做什么错?

评论

unix.stackexchange.com/a/251091/139312

#1 楼

您可以执行以下操作:

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

评论


请查看我在问题底部添加的内容。谢谢。

–兰德尔·库克(Randall Cook)
13年2月21日在19:25

没错,。和..是特殊目录:分别是当前目录和父目录。这只是一个警告。更好地使用shopt -s dotglob解决方案

–吉尔斯·奎诺(Gilles Quenot)
13年2月21日在19:27



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

–兰德尔·库克(Randall Cook)
13-2-22在4:19



如果使用的是zsh,则可以使用D globbing限定符或GLOB_DOTS shell选项。

– mgalgs
2014-12-23 23:39



不,。[!。] *是:点,后跟除点外的任何内容,后跟任何内容

–吉尔斯·奎诺(Gilles Quenot)
15年7月28日在9:20



#2 楼

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

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


评论


好点,@ AndrewSchwartz。我也喜欢这种方法。我认为它应该得到更多的认可。

–兰德尔·库克(Randall Cook)
15年7月28日在5:00

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

–HeyWatchThis
19年5月27日在22:58

如果非零退出代码是个问题,您可以将其取消,例如通过附加|| :(||表示对错误/错误执行以下命令::是noop命令)。但这也会抑制合法错误,例如目标文件夹不存在。我找不到使用mv排除的更优雅的方式。和..条目。通过cp对我来说最大的好处是不会将新文件写入磁盘。

–安德鲁·施瓦茨(Andrew Schwartz)
19年5月29日在13:30

#3 楼

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

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


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

如果这三个模式*中的任何一个都将出现错误, [^.]*..?*没有文件匹配,因此您只应包括匹配的文件。

评论


真好可以使用以下类似的答案解决此类问题:superuser.com/a/784046/144977。感谢您发布此信息。

– phyatt
16年12月21日在16:29

#4 楼

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

cp -Rp . /desired/directory


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

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

mv $(ls -A) /desired/directory


评论


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

–吉尔斯'所以-不再是邪恶的'
2014年6月14日13:04



到目前为止,这是一个很好的解决方案

– haidarvm
20-10-16在15:28

#5 楼

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

要复制带有glob的文件,您需要在文件前加上.前缀,例如mv -u .* foo,然后在出现以下情况时,.foo会显示为foo/.foo

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

评论


请查看我在问题底部添加的内容。谢谢。

–兰德尔·库克(Randall Cook)
13年2月21日在19:25

#6 楼

所以我们有:

a
|-- .foo
`-- bar


和:

b



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

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

$ mv --help


然后我找到了我的爱人:

$ mv a/ b/ -T


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


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


评论


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

–胸骨
15年7月28日在1:52

@thomasrutter,移动目录本身与重命名目录不一样吗?

–兰德尔·库克(Randall Cook)
15年7月28日在4:52

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

–胸骨
15年7月29日在0:17

#7 楼

以我为例,我只是尝试mv一个隐藏文件,而这就是解决方案:

FILE=.myHiddenFile
mv "$FILE" dest/


解释

起初我在尝试:

mv .myHiddenFile dest/


但是它继续产生错误:

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


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

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

#8 楼

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

cp -Rp source-directory/. .


评论


这与Drake Clarris在2013年的回答非常相似。您还有其他要补充的内容吗?

–兰德尔·库克(Randall Cook)
2016年9月6日下午5:02