Linux:如果不存在,则复制并创建目标目录

fly*_*ire 306 unix linux bash shell cp

我想要一个命令(或者可能是cp的一个选项),如果它不存在,则创建目标目录.

例:

cp -? file /path/to/copy/file/to/is/very/deep/there
Run Code Online (Sandbox Code Playgroud)

Mic*_*ker 276

mkdir -p "$d" && cp file "$d"
Run Code Online (Sandbox Code Playgroud)

(没有这样的选择cp).

  • 我认为你不需要`test -d`:即使目录已经存在,`mkdir -p`仍然成功. (59认同)
  • @holms,`$ d`是一个可能包含相关目录的变量.我的意思是,如果你必须重复三次,你可能会先将它分配给变量. (6认同)
  • @ssasi 不起作用,如果您提供尾随的“/”,则会说“目录不存在”,或者如果您不提供并且父目录存在,则复制为预期目录。是递归复制目录,而不是创建目录。 (2认同)

Pau*_*ipp 223

如果满足以下两个条件:

  1. 您使用的是GNU版本cp(而不是Mac版本),以及
  2. 您正在从一些现有的目录结构进行复制,您只需重新创建它

然后你可以用--parents旗帜做到这一点cp.从信息页面(可在http://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html#cp-invocation或用info cp或查看man cp):

--parents
     Form the name of each destination file by appending to the target
     directory a slash and the specified name of the source file.  The
     last argument given to `cp' must be the name of an existing
     directory.  For example, the command:

          cp --parents a/b/c existing_dir

     copies the file `a/b/c' to `existing_dir/a/b/c', creating any
     missing intermediate directories.
Run Code Online (Sandbox Code Playgroud)

例:

/tmp $ mkdir foo
/tmp $ mkdir foo/foo
/tmp $ touch foo/foo/foo.txt
/tmp $ mkdir bar
/tmp $ cp --parents foo/foo/foo.txt bar
/tmp $ ls bar/foo/foo
foo.txt
Run Code Online (Sandbox Code Playgroud)

  • 我觉得这是一个稍微不同的问题的答案,即使它是我正在寻找的答案(因此我赞成的那个).我想这是解决方案,假设您希望目标父目录与原始父目录相同,这可能是大多数人阅读此内容的用例. (18认同)
  • 男人,linux有_everything_ (16认同)
  • 这假设目录"bar"已经存在,但原始问题意味着如何在提供目标时自动创建"bar"并且它尚不存在.答案是由@ MichaelKrelin-hacker提供的. (7认同)
  • 我会说gnu具体.如果你有`macports`,你可以安装coreutils及其`gcp`. (6认同)
  • 这在Mac OS X上不起作用,所以我猜它是特定于Linux的. (3认同)
  • --parents有其用途,但是,例如,如果您仅想将目录创建基于目标路径(例如,将目录a / b中的文件c拷贝到目录d中)将无法使用。 / e / f`并根据需要创建目标路径)。 (2认同)

Mar*_*ery 55

简答

要复制myfile.txt/foo/bar/myfile.txt,请使用:

mkdir -p /foo/bar && cp myfile.txt $_
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

这有几个组件,所以我将逐步介绍所有语法.

MKDIR工具,如POSIX标准规定,使得目录.的-p说法,每文档,会造成MKDIR

创建任何缺少的中间路径名组件

意思是在调用时mkdir -p /foo/bar,mkdir将创建/foo , /foo/bar如果/foo还没有存在.(没有-p,它会抛出错误.

&&列表操作,如记录在POSIX标准(或猛砸手动,如果你喜欢),有效果cp myfile.txt $_,如果只得到执行mkdir -p /foo/bar成功执行.这意味着cp如果由于mkdir失败的原因之一而失败,则命令将不会尝试执行.

最后,$_作为第二个参数传递的cp是一个"特殊参数",它可以方便地避免重复长参数(如文件路径),而不必将它们存储在变量中.根据Bash手册,它:

扩展到上一个命令的最后一个参数

在这种情况下,/foo/bar我们传递给了mkdir.因此cp命令扩展为cp myfile.txt /foo/bar,复制myfile.txt到新创建的/foo/bar目录中.

请注意,$_不是 POSIX标准的一部分,所以理论上Unix的变种可能具有不支持此构建物的外壳.但是,我不知道任何不支持的现代炮弹$_; 当然Bash,Dash和zsh都这样做.


最后一点:我在本回答开头给出的命令假设您的目录名称没有空格.如果您要处理带空格的名称,您需要引用它们以便使用不同的单词不被视为mkdir或的不同参数cp.所以你的命令实际上看起来像:

mkdir -p "/my directory/name with/spaces" && cp "my filename with spaces.txt" "$_"
Run Code Online (Sandbox Code Playgroud)

  • 除此之外:我常常对Stack Overflow中关于Bash或Unix shell命令的问题缺乏细节感到失望,这些命令常常会抛出一个复杂且极其密集的单行程,如果你还不是Unix向导那么它很难解开.我试图在这里采取相反的极端,并解释语法的每个细节,并链接到适当的位置,以找到有关这些东西如何工作的文档.我希望这至少对一些人有帮助.此外,还款到期:我从这个问题的答案中删除了这个方法:http://stackoverflow.com/a/14085147/1709587 (14认同)
  • @thebunnyrules但是......但是......有一个**"这是如何工作的?"**我的答案中的部分字面上包含多个专门针对你刚问的问题的段落.感觉被忽视和不受欢迎.:( (8认同)

hel*_*sap 35

这么老的问题,但也许我可以提出一个替代解决方案.

您可以使用该install程序复制文件并"动态"创建目标路径.

install -D file /path/to/copy/file/to/is/very/deep/there/file
Run Code Online (Sandbox Code Playgroud)

但是,有一些方面需要考虑:

  1. 您还需要指定目标文件名,而不仅是目标路径
  2. 目标文件将是可执行的(至少,就我从测试中看到的那样)

您可以通过添加-m用于设置目标文件权限的选项轻松修改#2 (例如:-m 664将创建具有权限的目标文件rw-rw-r--,就像创建新文件一样touch).


在这里它是答案无耻链接我受到启发 =)

  • 请注意,此命令创建具有“755”(“rwxr-xr-x”)权限的目标文件,这可能是不需要的。您可以使用“-m”开关指定其他内容,但我找不到一种方法来_保留_文件权限:( (5认同)

And*_*oss 17

Shell函数可以执行您想要的操作,将其称为"埋葬"副本,因为它为文件挖掘了一个漏洞:

bury_copy() { mkdir -p `dirname $2` && cp "$1" "$2"; }
Run Code Online (Sandbox Code Playgroud)

  • @Kalmi,对于正确的引用,你也想引用`$ 2`作为`dirname`的参数.比如`mkdir -p"$(dirname"$ 2")"`.没有这个引用`$ 2`在`cp`是没用的;) (4认同)
  • 请注意,这个答案假设$ 2不是目标目录,否则你只需要"mkdir -p"$ 2"&& cp"$ 1""$ 2"作为函数体 (3认同)

Jam*_*dle 10

这是一种方法:

mkdir -p `dirname /path/to/copy/file/to/is/very/deep/there` \
   && cp -r file /path/to/copy/file/to/is/very/deep/there
Run Code Online (Sandbox Code Playgroud)

dirname将为您提供目标目录或文件的父级.然后mkdir -p`dirname ...`将创建该目录,确保在调用cp -r时,正确的基本目录就位.

这种过度父母的优点是它适用于目标路径中的最后一个元素是文件名的情况.

它将适用于OS X.


小智 9

这已经很晚了,但它可能会在某个地方对新手有所帮助。如果您需要自动创建文件夹rsync应该是您最好的朋友。

rsync /path/to/sourcefile /path/to/tragetdir/thatdoestexist/
Run Code Online (Sandbox Code Playgroud)


Ler*_*unn 8

这对我有用

cp -vaR ./from ./to
Run Code Online (Sandbox Code Playgroud)


Dig*_*Dig 7

正如上面 help_asap 和 Spongeman 所建议的,您可以使用“install”命令将文件复制到现有目录,或者创建新的目标目录(如果它们尚不存在)。

选项 1 install -D filename some/deep/directory/filename
将文件复制到新的或现有的目录并赋予文件名默认 755 权限

选项 2 install -D filename -m640 some/deep/directory/filename
与选项 1 相同,但提供文件名 640 权限。

选项 3 install -D filename -m640 -t some/deep/directory/
与选项 2 相同,但将文件名定位到目标目录中,因此不需要在源和目标中都写入文件名。

选项 4 install -D filena* -m640 -t some/deep/directory/
与选项 3 相同,但对多个文件使用通配符。

它在 Ubuntu 中运行良好,并将两个步骤(目录创建然后文件复制)合并为一个步骤。


SD.*_*SD. 6

只需在 .bashrc 中添加以下内容,并根据需要进行调整。在 Ubuntu 中工作。

mkcp() {
    test -d "$2" || mkdir -p "$2"
    cp -r "$1" "$2"
}
Run Code Online (Sandbox Code Playgroud)

例如,如果您想将“test”文件复制到目标目录“d”,请使用,

mkcp test a/b/c/d
Run Code Online (Sandbox Code Playgroud)

mkcp将首先检查目标目录是否存在,如果不存在则创建它并复制源文件/目录。

  • 正如其他人对其他答案的评论,您不需要在调用“mkdir -p”之前测试目录是否存在。即使它已经存在,它也会成功。 (2认同)

Spo*_*man 6

install -D file -m 644 -t /path/to/copy/file/to/is/very/deep/there

  • 这适用于单个文件。只需考虑到“there”是最终文件,而不是最终子目录。 (2认同)

小智 6

只是为了恢复并在一行中提供完整的工作解决方案。如果您想重命名文件,请小心,您应该包含一种为 mkdir 提供干净的目录路径的方法。$fdst 可以是文件或目录。下一个代码应该在任何情况下都有效。

fsrc=/tmp/myfile.unk
fdst=/tmp/dir1/dir2/dir3/myfile.txt
mkdir -p $(dirname ${fdst}) && cp -p ${fsrc} ${fdst}
Run Code Online (Sandbox Code Playgroud)

或 bash 特定

fsrc=/tmp/myfile.unk
fdst=/tmp/dir1/dir2/dir3/myfile.txt
mkdir -p ${fdst%/*} && cp -p ${fsrc} ${fdst}
Run Code Online (Sandbox Code Playgroud)


小智 6

无需创建脚本并使用简单的命令...

mkdir -p /destination-folder/ && cp file-name /destination-folder/
Run Code Online (Sandbox Code Playgroud)


mar*_*han 5

考虑到以上所有答案,我更喜欢按以下方式使用rsync:

$  rsync -a directory_name /path_where_to_inject_your_directory/
Run Code Online (Sandbox Code Playgroud)

例:

$ rsync -a test /usr/local/lib/
Run Code Online (Sandbox Code Playgroud)

  • ```rsync``` 比 ```cp``` 更可预测。例如,如果我希望 ```cp /from/somedir /to-dir``` 那么 cp 的行为会有所不同,如果 ```/to-dir``` 已经存在: 如果 ```/to-dir`` ` 存在,则 ``cp``` 将创建 ```/to-dir/some-dir```,否则仅将 ```/from/somedir``` 的内容放入 ```/到目录``` 。然而,“rsync”的行为是相同的,即“/to-dir/some-dir”将_总是_被创​​建。 (2认同)