要从我读过的文件夹中复制内容,请使用:
cp -rfva ../foldersource/. ./
但这也有效
cp -rfva ../foldersource/* ./
有什么区别吗?
举例来说,如果我想从带有 . :
rm -rf ../foldersource/.
我收到错误:
rm: rejet delete folder '.' or '..':
但带星号就可以了
rm -rf ../foldersource/*
那么,星号是在任何地方都适用的更好选择吗?
答案1
这两种论证形式之间存在根本区别。了解正在发生的事情非常重要。
参数../foldersource/.
会原封不动地传递给命令,无论它是cp
或rm
其他东西。尾随点是否具有特殊或独特的语义,与简单地指向它所在目录的标准 Unix 约定不同,这取决于命令;两者rm
似乎cp
都将其视为特殊情况。
和../foldersource/*
首先由 shell 扩展前该命令甚至会被执行并传递任何参数。因此,rm
从未见过../foldersource/*
;它看到扩展版本../foldersource/file1.ext ../foldersource/file2.ext ../foldersource/childfolder1
等等。这很重要,因为操作系统限制可以传递给命令的参数数量,通常只有几百个。
答案2
当您使用复制时,cp -a source/* target/
您会将大部分文件和目录从 复制source
到target
。具体来说,被排除的项目可能是 .txt 文件.
的顶层以点 ()开头的文件source
。
考虑这些文件(或目录)source
apple # will be copied
banana/ # will be copied, as will all its contents
.cherry # will not be copied
当您使用 进行复制时,cp -a source/. target/
您将复制 的全部内容source
,包括以点 ( .
) 开头的任何项目到target
考虑这些文件(或目录)source
apple # will be copied
banana/ # will be copied, as will all its contents
.cherry # will be copied
如果您使用bash
, zsh
,则可以使用dotglob
选项更改 的含义,*
使其包含以点开头的文件和目录(yash
也有一个dotglob
选项;但是,它随后在 glob 扩展中包含.
and ..
,这限制了其可用性。另请参阅FIGNORE='@(.|..)'
)ksh93
。
有趣的是,cp -a source/. target/
有保证绝不创建组件target/source
。 (另一方面,cp -a source target/
将根据是否target
已存在执行两件事之一。请参阅如何使用 cp 以幂等方式递归复制文件夹了解详情。)
使用删除时,您将删除其中不以点 ( ) 开头rm -rf source/*
的文件和目录。取决于我已经提到的设置。它不会删除目录本身。source
.
dotglob
source
当您尝试使用它删除时,rm -rf source/.
它将失败 - 如其他人已经解释过- 因为 POSIX 禁止删除最后一个组件是.
或 的路径..
。最接近的等效项是rm -rf source
,它将删除source
目录及其所有内容,无论它们是否以点 ( .
) 开头。
答案3
您不能这样做,rm -rf ../foldersource/.
因为rm
不允许这样做,如手册中明确指出的:
任何删除最后一个文件名部分为“.”的文件的尝试或 '..' 在没有任何提示的情况下被拒绝,按照 POSIX 的规定。
在 POSIX 手册中man 1p rm
我们看到:
如果文件 dot 或 dot-dot 被指定为操作数的基名部分(即最终路径名部分),或者如果操作数解析为根目录,则 rm 应将诊断消息写入标准错误并且不执行任何操作更多这样的操作数。