¿Cómo puedo copiar un archivo y crear los directorios de destino al mismo tiempo?

20

Quiero cp aaa/deep/sea/blob.psdabbb/deep/sea/blob.psd

¿Cómo hago la copia si los directorios deepy seano existen bbbpara que la copia cree los directorios necesarios y copie el archivo?

Ahora mismo me pongo
No such file or directorytan profundo y el mar no existe.

Miré a través de las páginas de ayuda del hombre y otras preguntas, pero nada salta a la vista.

Lo más cercano que tengo es usar rcppara el directorio:

rcp -r aaa/deep/sea/ bbb/deep/sea/

aunque esto copia todo el directorio y el contenido y solo quiero un archivo. Intentar hacer eso sin embargo diocp: cannot create regular file bbb/deep/sea/blob.psd' such file or directory

Michael Durrant
fuente

Respuestas:

19

Intente usar la siguiente función para tal situación:

copy_wdir() { mkdir -p -- "$(dirname -- "$2")" && cp -- "$1" "$2" ; }

y úsalo como

copy_wdir aaa/deep/sea/blob.psd bbb/deep/sea/blob.psd

Por cierto, GNU cptiene una --parentsopción. Está realmente cerca de lo que quieres, pero no exactamente.
También creará un aaadirectorio que parece que no necesita. Sin embargo, primero puede cd aaay copiar como:

cd aaa && cp --parents deep/sea/blob.psd ../bbb/
prisa
fuente
24

Es fácil usar el installprograma de coreutils que normalmente se usa para este mismo propósito en sistemas de compilación como automake :

install -D /path/to/source /path/to/destination

Tenga en cuenta que installcrea todas las partes de la ruta al igual que lo mkdir -phace, vea man install. Tengo curiosidad por qué no incluiste por qué quieres hacer eso. Llamar mkdiry cpes muy fácil.

Pavel Šimerda
fuente
2
Creo que hay muchas buenas respuestas a esta pregunta, pero esta tiene mi voto, ya que es la más portátil. La rsyncrespuesta solo creará 1 directorio, y paxno parece ser común.
Patrick
Usar en -dlugar de -Den una Mac.
Matt M.
tenga en cuenta que este comando crea los archivos de destino con permisos 755( rwxr-xr-x), lo que probablemente no se desea. puede especificar algo más con el -minterruptor, pero no pude encontrar una manera de mantener los permisos del archivo :(
törzsmókus
6

Con los comandos estándar (POSIX / Unix), tienes:

pax -rws ':^:dest/dir/:' file .
Stéphane Chazelas
fuente
1
Interesante. Nunca había oído hablar de pax antes. Aunque me gusta su concepto. Desafortunadamente, aunque está en POSIX, parece que muy pocas distribuciones lo instalan por defecto :-(
Patrick
@Patrick - si saltas hasta el final de info tar- en algún lugar de la sección de preocupaciones de portabilidad - creo que encontrarás que GNU tarafirma ser totalmente paxcompatible. Lo hice de todos modos, aunque todavía no he podido poner a prueba esas afirmaciones.
mikeserv
5

No conozco una forma de hacerlo usando cp, pero ciertamente es posible usando rsync:

$ rsync sourcefile dir/

donde dires un directorio que no tiene que existir. Hay muchas otras formas de lograr lo mismo con otros comandos.

mjturner
fuente
3
Es necesario rsync -Rpara preservar la jerarquía de directorios
Jackman Glenn
@glennjackman De hecho, el uso 'adecuado' de las rsyncnecesidades necesita más opciones, pero la pregunta era simplemente sobre la creación de un directorio de destino inexistente, de ahí mi breve respuesta :)
mjturner
1
Al menos el GNU cptiene la --parentsopción.
Peter
2
@peterph De hecho, pero entonces está restringido en el nombre del directorio de destino
mjturner
4
cd aaa
pax -rw deep/sea/blob.psd ../bbb

Si no tiene pax(es obligatorio por POSIX, como un reemplazo estándar de cpio y tar que tenía demasiadas incompatibilidades para estandarizar), use cpio -po en su tar -cf - … | tar -xf -lugar.

Gilles 'SO- deja de ser malvado'
fuente