Linux: copie y cree el directorio de destino si no existe

Resuelto flybywire asked hace 14 años • 29 respuestas

Quiero un comando (o probablemente una opción para cp) que cree el directorio de destino si no existe.

Ejemplo:

cp -? file /path/to/copy/file/to/is/very/deep/there
flybywire avatar Oct 07 '09 13:10 flybywire
Aceptado
mkdir -p "$d" && cp file "$d"

(no existe tal opción para cp).

Michael Krelin - hacker avatar Oct 07 '2009 06:10 Michael Krelin - hacker

Si ambas de las siguientes son verdaderas:

  1. Está utilizando la versión GNU de cp(y no, por ejemplo, la versión para Mac), y
  2. Estás copiando desde alguna estructura de directorio existente y solo necesitas recrearla

entonces puedes hacer esto con la --parentsbandera de cp. Desde la página de información (que se puede ver en http://www.gnu.org/software/coreutils/manual/html_node/cp-invocation.html#cp-invocation o con info cpo 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.

Ejemplo:

/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
Paul Whipp avatar Jan 04 '2012 06:01 Paul Whipp

Respuesta corta

Para copiar myfile.txta /foo/bar/myfile.txt, utilice:

mkdir -p /foo/bar && cp myfile.txt $_

¿Cómo funciona esto?

Hay algunos componentes en esto, así que cubriré toda la sintaxis paso a paso.

La utilidad mkdir , como se especifica en el estándar POSIX , crea directorios. El -pargumento, según los documentos, hará que mkdir

Cree cualquier componente de nombre de ruta intermedio que falte

lo que significa que al llamar mkdir -p /foo/bar, mkdir creará /foo y /foo/bar si /fooaún no existe. (Sin -p, arrojará un error.

El &&operador de lista, como está documentado en el estándar POSIX (o el manual de Bash si lo prefiere), tiene el efecto de que cp myfile.txt $_solo se ejecuta si mkdir -p /foo/barse ejecuta correctamente. Esto significa que el cpcomando no intentará ejecutarse si mkdirfalla por una de las muchas razones por las que podría fallar .

Finalmente, lo que $_pasamos como segundo argumento cpes un "parámetro especial" que puede ser útil para evitar repetir argumentos largos (como rutas de archivos) sin tener que almacenarlos en una variable. Según el manual de Bash ,:

se expande al último argumento del comando anterior

En este caso, ese es el que /foo/barpasamos mkdir. Entonces el cpcomando se expande a cp myfile.txt /foo/bar, que se copia myfile.txten el /foo/bardirectorio recién creado.

Tenga en cuenta que no$_ forma parte del estándar POSIX , por lo que, en teoría, una variante de Unix podría tener un shell que no admita esta construcción. Sin embargo, no conozco ningún shell moderno que no sea compatible con ; ciertamente Bash, Dash y zsh lo hacen.$_


Una nota final: el comando que di al comienzo de esta respuesta supone que los nombres de su directorio no tienen espacios. Si está tratando con nombres con espacios, deberá citarlos para que las diferentes palabras no se tratan como argumentos diferentes de mkdiro cp. Entonces tu comando realmente se vería así:

mkdir -p "/my directory/name with/spaces" && cp "my filename with spaces.txt" "$_"
Mark Amery avatar Sep 15 '2015 22:09 Mark Amery