Linux: copie y cree el directorio de destino si no existe
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
mkdir -p "$d" && cp file "$d"
(no existe tal opción para cp
).
Si ambas de las siguientes son verdaderas:
- Está utilizando la versión GNU de
cp
(y no, por ejemplo, la versión para Mac), y - Estás copiando desde alguna estructura de directorio existente y solo necesitas recrearla
entonces puedes hacer esto con la --parents
bandera 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 cp
o 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
Respuesta corta
Para copiar myfile.txt
a /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 -p
argumento, 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 /foo
aú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/bar
se ejecuta correctamente. Esto significa que el cp
comando no intentará ejecutarse si mkdir
falla por una de las muchas razones por las que podría fallar .
Finalmente, lo que $_
pasamos como segundo argumento cp
es 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/bar
pasamos mkdir
. Entonces el cp
comando se expande a cp myfile.txt /foo/bar
, que se copia myfile.txt
en el /foo/bar
directorio 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 mkdir
o cp
. Entonces tu comando realmente se vería así:
mkdir -p "/my directory/name with/spaces" && cp "my filename with spaces.txt" "$_"