情况 :
$ mkdir foo && touch foo/.test
$ cp foo/* .
zsh: no matches found: foo/*
(or bash : cp: cannot stat ‘foo/*’: No such file or directory)
我有一个充满隐藏文件夹和文件的目录。发生了什么以及解决方案是什么?
答案1
答案2
免责声明:这个答案专门针对 Bash,但其中大部分适用于有关全局模式的问题!
星号 ( *
) 是通配符。它将取代某些特定的字符集,并且第一个字符是点 ( .
) 不是其中之一。这是一个特殊情况,只是因为 Unix 文件系统的工作方式,以点开头的文件被视为“隐藏”。这意味着诸如 、 等工具cp
不会ls
“看到”它们,除非明确告知这样做。
例子
首先让我们创建一些示例数据。
$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}
所以现在我们有以下内容:
$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3
现在让我们玩一些游戏。您可以使用该命令echo
列出*
给定命令的特定通配符 ( ),如下所示:
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3
$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3
$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2
$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
$ echo .dotdir*
.dotdir1 .dotdir2
改变行为?
您可以使用该命令shopt -s dotglob
更改 的行为,*
以便除了类似的文件之外,regfile1
它也会匹配.dotfile1
.
bash
手册页摘录
dotglob If set, bash includes filenames beginning with a `.' in the results
of pathname expansion.
例子:
$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
您可以使用以下命令恢复此行为:
$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3
你的情况?
对于您来说,您告诉cp
您要复制与模式匹配的所有文件*
,但没有任何文件。
$ cp foo/.* .
或者,如果您想要文件夹中的所有内容,您可以这样做foo
:
$ cp foo .
或者你可以明确地说:
$ cp foot/.* foo/* .
使用大括号扩展的更紧凑形式bash
:
$ cp foo/{.,}* .
您可以随时使用该echo
技巧来查看您建议的文件模式(这是星号所属部分的奇特术语)。
$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3
顺便说一句,如果您要复制文件目录+其他目录,您通常希望递归地执行此操作,即切换-R
到cp
:
$ cp -R foo/. .
答案3
shell 在解析字符时将这些文件视为隐藏文件*
,因此cp
不会接收任何这些文件名作为参数。
您可以通过显式指定来复制它们cp foo/.* .
答案4
如果您想要做的是将所有文件和目录从一个地方复制到另一个地方,您可以使用标准rsync
命令。在您上面给出的示例中:
mkdir foo && touch foo/.test
rsync -a foo/ .
将递归地将 的所有内容foo
(包括隐藏文件和隐藏目录)复制到当前目录中。末尾的斜杠foo/
对于 rsync 很重要;使用它只会foo
复制的内容,没有它 rsync 也会复制foo
。例如:-
mkdir src && mkdir dest && touch src/.test
rsync -a src dest // copies 'src' contents to 'dest/src'
rsync -a src/ dest // copies 'src' contents to 'dest'
还有许多其他选项可以调整 rsync,包括在机器之间复制。