如何让 mv (或 * 通配符)移动隐藏文件?

Ran*_*ook 174 command-line bash

我正在将我的主目录从旧系统迁移到新系统,我制作的 tarball 包含所有内容,包括像 .bashrc 这样的隐藏文件。但是,当我将解压缩的 tarball(位于 /tmp 中)的内容移动到我的新主目录时,隐藏文件不会复制 ( mv /tmp/home/rcook/* /home/rcook/)。我怎样才能让 mv 移动它们?

实际上,我认为问题不在于 mv,而在于 bash 的 globbing。如果我这样做:

mkdir a
mkdir b
touch a/.foo
touch a/bar
mv a/* b/
ls -a a/ b/
Run Code Online (Sandbox Code Playgroud)

我看到这个:

a/:
.  ..  .foo

b/:
.  ..  bar
Run Code Online (Sandbox Code Playgroud)

a/.foo没动。那么如何获取 * 通配符来查找隐藏文件呢?

是的,我想我可以直接解压缩包到我的主目录,但将压缩包解压缩到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
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

Gil*_*not 185

你可以这样做 :

shopt -s dotglob
mv /tmp/home/rcook/* /home/rcook/
Run Code Online (Sandbox Code Playgroud)

你可以放

shopt -s dotglob
Run Code Online (Sandbox Code Playgroud)

~/.bashrc如果您希望它成为默认值,则在您的。

http://mywiki.wooledge.org/glob


复制点文件的另一种方法:

mv /tmp/home/rcook/.[!.]* /home/rcook/
Run Code Online (Sandbox Code Playgroud)

不要使用..*匹配的模式..(指向父目录的指针)。如果存在名称以两个点 ( ..something)开头的文件,也使用模式..?*.

  • 如果你使用 `zsh`,你可以使用 [`D` 通配符](http://unix.stackexchange.com/a/89771/3587) 或 [`GLOB_DOTS` shell 选项](http://unix.stackexchange.com/a/89771/3587) /superuser.com/a/373751/70130)。 (3认同)

小智 58

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

mv src/* src/.* dst/
Run Code Online (Sandbox Code Playgroud)

您仍然会收到 . 和 .. 条目,这很好。但此举应该会成功。

~/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
Run Code Online (Sandbox Code Playgroud)

  • 好点,@AndrewSchwartz。我也喜欢这种方法。我认为它值得更多的认可。 (3认同)

Aza*_*mat 14

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

mv /tmp/home/rcook/{*,.[^.]*,..?*} /home/rcook/
Run Code Online (Sandbox Code Playgroud)

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

如果三个模式中的任何一个*[^.]*或者不..?*匹配任何文件,你都会得到一个错误,所以你应该只包含匹配的那些。


tca*_*arv 10

我知道这很旧,但是,一种简单的方法是:

mv a/{.*,*} b/
Run Code Online (Sandbox Code Playgroud)

解释

这称为大括号扩展。在这种情况下,shell 通过连接大括号之前给出的字符串(在本例中为a/)和大括号包围的列表中给出的每个变体来扩展您给出的路径。变体列表由用逗号分隔的值组成,并再次用大括号括起来。因此,在本例中,我们有.**作为元素,因此列表必须是{.*,*}

mv a/{.*,*} b/
Run Code Online (Sandbox Code Playgroud)

上面的表达式可以这样理解:将目录中以点 ( .*)开头的所有文件以及其他任何内容 ( *)移动a/到该b/目录。

更多提示

这非常有帮助,可以在各种场景中使用。例如,假设您必须使用以下命名模式创建 100 个文件:file1、file2、file3...file100。通过这样做你可以轻松实现它

touch file{1..100}
Run Code Online (Sandbox Code Playgroud)

在本例中,您可以看到给出了一个范围。您可以通过用两个点 ( ..) 分隔第一个值和最后一个值来实现此目的。

超越!

我是 Unix 世界的新手,即使知道它可以在bashzsh(我到目前为止使用过的 shell)中工作,我也不能保证它可以在任何 shell 中工作。

您可以在 shell 文档中查看有关扩展和通配符man bash更多信息(分别使用:或man zshall,分别表示 bash 和 zsh)。

希望这对未来的读者有所帮助!

  • 如果你写成`{*,.*}`,它也是一个表情符号 (2认同)

Dra*_*ris 9

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

cp -Rp . /desired/directory
Run Code Online (Sandbox Code Playgroud)

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

或者,如果您知道文件的名称很合理(没有空格、通配符、不可打印的字符),您可以执行以下操作

mv $(ls -A) /desired/directory
Run Code Online (Sandbox Code Playgroud)

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

dob*_*bey 5

Linux 上并不存在真正的“隐藏”文件。默认情况下,以点开头的文件在文件列表中隐藏。

要复制带有 glob 的文件,您需要在文件前添加前缀.mv -u .* foo然后.foo将显示为foo/.foo移动时的样子。

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