仅将常规文件从一个目录复制到另一个目录

use*_*398 18 cp files

我想将目录 1 的内容复制到目录 2。但是,我只想从目录 1 中复制文件(而不是目录)。我该怎么做?

cp dir1/* dir2/*
Run Code Online (Sandbox Code Playgroud)

那么我仍然有目录问题。

此外,我所有的文件都没有任何扩展名,所以. 不会做的伎俩

Ada*_*hon 23

cp dir1/* dir2
Run Code Online (Sandbox Code Playgroud)

cp除非明确告知,否则不会复制目录(--recursive例如,参见man cp)。

注 1: cp很可能会以非零状态退出,但无论如何文件都会被复制。基于退出代码链接命令时,这可能是一个问题:&&||if cp -r dir1/* dir2; then ...等(感谢contrebis他们在这个问题上的评论

注 2cp期望最后一个参数是单个文件名或目录。*目标目录的名称后确实不应该有通配符。dir2\*将像dir1\*. 意想不到的事情发生:

  • 如果dir2为空,取决于您的外壳和设置:
    • 您可能只会收到一条错误消息,这是最好的情况。
    • dir2/*将按字面理解(查找名为 的文件/目录*),这也可能导致错误,除非*确实存在。
    • dir2/*它将完全从命令中删除,而将cp dir1/*. 其中,根据 的扩展dir1/*,甚至可能破坏数据:
      • 如果dir1/*只匹配一个文件或目录,您将收到来自cp.
      • 如果dir1/*正好匹配两个文件,一个将被另一个 ( Bad )覆盖。
      • 如果dir/*匹配多个文件并且最后一个匹配是a,您将收到错误消息。
      • 如果最后一个匹配项dir/*是一个目录,则所有其他匹配项都将移动到该目录中。
  • 如果dir2不为空,则再次取决于:
    • 如果 的最后一个匹配dir2/*是一个目录,dir1/*则其他匹配的dir2/*将被移入。
    • 如果最后匹配的dir2/*是一个文件,您可能会收到一条错误消息,除非 dir1/*只匹配一个文件。

  • 是的,它也以状态 1 退出。但即便如此,`cp` 确实会在我检查过的每个系统上复制与 `dir1/*` 匹配的文件:Arch Linux、Ubuntu 14.04、OpenBSD 3.9 和 5.5、SuSE Linux 8.1、FreeBSD 6.2、Solaris 8、9 和 10(其中` cp` 实际上以代码 2 退出)。所以这种行为既不是新的(SuSE 8.1 是 2002 年的),也不限于 Linux。`cp` 以非零退出代码退出,因为它不能做*它被告知要做的*所有事情。这并不意味着它什么都不做*。 (3认同)
  • 当然,我认为值得注意,因为如果您将命令与 `&&` 链接在一起,这可能会导致问题。虽然我现在不记得上下文了,但我正在尝试这样的事情。 (3认同)

Gil*_*il' 10

扩展通配符的是shell,而不是命令。所以cp dir1/* dir2/*首先扩展两个通配符,然后调用cp结果。这完全不是您所期望的:根据 中已有的文件数量dir2dir2/*可能会扩展为一个或多个参数。该命令cp不知道哪些参数来自扩展第一个模式,哪些来自扩展第二个模式。它期望它的最后一个参数是目标目录的名称。因此,要将目录中的所有文件复制dir1到目录中dir2,最后一个参数必须是目录dir2

cp dir1/* dir2
Run Code Online (Sandbox Code Playgroud)

由于*匹配所有文件,cp尝试复制所有文件。这包括目录:目录也是文件。它跳过目录,但报告错误。它复制特殊文件的内容,例如命名管道(最好向它们写入内容,否则cp会阻塞)等。

要仅复制常规文件,您需要限制匹配。在 zsh 中,您可以使用glob 限定符 .

cp dir1/*(.) dir2
Run Code Online (Sandbox Code Playgroud)

其他贝壳没有这个。您可以使用该find命令过滤文件类型。假设您运行的是非嵌入式 Linux 或 Cygwin:

find dir1 -maxdepth 1 -type f -exec cp -t dir2 {} +
Run Code Online (Sandbox Code Playgroud)

在 Linux、FreeBSD 和 OSX 上:

find dir1 -maxdepth 1 -type f | xargs -I {} cp {} dir2
Run Code Online (Sandbox Code Playgroud)

  • @Abdull 如果没有“-maxdepth 1”,“find”命令将递归到子目录,这在这里是不需要的。如果您想复制整个目录树(包括子目录),这是一个完全不同的问题,答案要简单得多:`cp -a dir1 dir2`。 (2认同)