Linux:复制并创build目标目录,如果它不存在
我想要一个命令(或者可能是cp的一个选项)创build目标目录,如果它不存在。
例:
cp -? file /path/to/copy/file/to/is/very/deep/there
test -d "$d" || mkdir -p "$d" && cp file "$d"
(对于cp
没有这个选项)。
如果以下两者都是正确的:
- 您正在使用
cp
的GNU版本(而不是,例如,Mac版本)和 - 你正在复制一些现有的目录结构,你只需要重新创build它
那么你可以用cp
的--parents
标志来做到这一点。 从信息页面(可在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.
例:
/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
这样一个老问题,但也许我可以提出一个替代解决scheme。
您可以使用install
程序来复制您的文件并“即时”创build目标path。
install -D file /path/to/copy/file/to/is/very/deep/there/file
但是有一些方面需要考虑,
- 您还需要指定目标文件名称 ,而不仅仅是目标path
- 目标文件将是可执行的 (至less,据我看到我的testing)
通过添加-m
选项来设置目标文件的权限(例如: -m 664
将创build具有权限rw-rw-r--
的目标文件,就像通过touch
创build新文件一样),可以轻松修改#2。 。
这里是我被启发的答案的无耻链接 =)
简答
要将myfile.txt
复制到/foo/bar/myfile.txt
,请使用:
mkdir -p /foo/bar && cp myfile.txt $_
这个怎么用?
这里有几个组件,所以我将逐步介绍所有的语法。
在POSIX标准中指定的mkdir实用程序生成目录。 -p
参数,根据文档,将导致mkdir
创build任何缺less的中间path名组件
这意味着当调用mkdir -p /foo/bar
,如果/foo
不存在, mkdir将创build/foo
和 /foo/bar
。 (没有-p
,它会抛出一个错误。
在POSIX标准 (或Bash手册,如果您愿意的话)中logging的&&
列表操作符具有如下效果:如果mkdir -p /foo/bar
成功执行,则仅执行cp myfile.txt $_
。 这意味着如果mkdir
失败, cp
命令将不会尝试执行,原因很多,可能会失败 。
最后,作为cp
的第二个parameter passing的$_
是一个“特殊参数”,它可以方便地避免重复长参数(如文件path),而不必将它们存储在variables中。 根据Bash手册 ,它:
扩展到上一个命令的最后一个参数
在这种情况下,这就是我们传递给mkdir
的/foo/bar
。 因此, cp
命令扩展为cp myfile.txt /foo/bar
,它将myfile.txt
复制到新创build的/foo/bar
目录中。
请注意, $_
不是 POSIX标准的一部分 ,因此理论上Unix变体可能有一个不支持这种结构的shell。 但是,我不知道任何现代的炮弹不支持$_
; 当然Bash,Dash和zsh都可以。
最后一点:我在这个答案开始时给出的命令假设你的目录名没有空格。如果你用空格处理名字,你需要引用它们,以便不同的单词不被视为mkdir
或cp
不同参数。 所以你的命令实际上是这样的:
mkdir -p "/my directory/name with/spaces" && cp "my filename with spaces.txt" "$_"
Shell函数根据需要调用它,将其称为“埋藏”副本,因为它为该文件挖掘出一个空洞:
bury_copy() { mkdir -p `dirname $2` && cp "$1" "$2"; }
以下是一种方法:
mkdir -p `dirname /path/to/copy/file/to/is/very/deep/there` \ && cp -r file /path/to/copy/file/to/is/very/deep/there
dirname
会给你的目的地目录或文件的父。 mkdir -p`dirname …`然后创build该目录,确保当你调用cp -r时,正确的基目录就位。
这种超级父母的优点是,它适用于目的地path中的最后一个元素是文件名的情况。
它将在OS X上工作。
install -D file -m 644 -t /path/to/copy/file/to/is/very/deep/there
cp
有多种用法:
$ cp --help Usage: cp [OPTION]... [-T] SOURCE DEST or: cp [OPTION]... SOURCE... DIRECTORY or: cp [OPTION]... -t DIRECTORY SOURCE... Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.
@ AndyRoss的答案适用于
cp SOURCE DEST
cp
风格,但是如果你使用的是错误的东西
cp SOURCE... DEST/
cp
风格。
我认为在这种用法(即目标目录尚不存在的情况下)中,“DEST”是不明确的,这也许是为什么cp
从未为此添加过一个选项。
所以这里是我的这个函数的版本,它在dest目录上强制执行尾部的斜杠:
cp-p() { last=${@: -1} if [[ $# -ge 2 && "$last" == */ ]] ; then # cp SOURCE... DEST/ mkdir -p "$last" && cp "$@" else echo "cp-p: (copy, creating parent dirs)" echo "cp-p: Usage: cp-p SOURCE... DEST/" fi }
只需在你的.bashrc中添加以下内容,如果你需要的话。 在Ubuntu中工作。
mkcp() { test -d "$2" || mkdir -p "$2" cp -r "$1" "$2" }
例如,如果您想将“testing”文件复制到目标目录“d”使用,
mkcp test a/b/c/d
mkcp将首先检查目标目录是否存在,如果不存在,则复制源文件/目录。
从源复制到不存在的path
mkdir -p / destination && cp -r / source / $ _
注意:这个命令复制所有的文件
cp -r复制所有文件夹及其内容
$ _作为在上一个命令中创build的目的地
与我所有的尊重上面的答案,我更喜欢使用rsync如下:
$ rsync -a directory_name /path_where_to_inject_your_directory/
例:
$ rsync -a test /usr/local/lib/
rsync file /path/to/copy/file/to/is/very/deep/there
你走了,没有问题问。
假设你正在做类似的事情
cp file1.txt A / B / C / D / file.txt
A / B / C / D是不存在的目录
一个可能的解决scheme如下
DIR=$(dirname A/B/C/D/file.txt) # DIR= "A/B/C/D" mkdir -p $DIR cp file1.txt A/B/C/D/file.txt
希望有所帮助!