¿Puedo también mover o copiar la jerarquía de directorios de un archivo cuando yo mv
o cp
el archivo?
Por ejemplo, si soy yo mv
o cp
dir1/dir2/file
en otro lugar, solo será mv
o cp
file
. ¿Qué pasa si quiero también mv
o cp
dir1/dir2
? En lugar de mkdir -p dir1/dir2
, ¿se puede hacer con un solo comando?
Respuesta1
Puedes usar el interruptor cp
de :--parents
$ mkdir -p step1/step2/step3
$ touch step1/step2/step3/file
$ mkdir copy
$ cp --parents step1/step2/step3/file copy
$ ls copy/step1/step2/step3/file
copy/step1/step2/step3/file
mv
, sin embargo, no tiene un --parents
interruptor, pero podrías hacer algo como:
$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete
Que lo hará:
- Encuentra el archivo.
- Cópialo (junto con sus padres) al destino.
- Eliminar el original.
Podrías crear una función para esto:
mvparents()
{
[[ $# -ne 2 ]] && echo "2 arguments needed." && return
[[ ! -r "$1" ]] && echo "$1 is not readable." && return
[[ ! -d "$2" ]] && mkdir -p "$2"
find $(dirname $1) -name "$(basename $1)" -exec cp --parents {} $2/ \; -delete
}
$ mvparents step1/step2/step3/file copy/
Sin embargo, esto puede requerir algunos ajustes si intentas mover varios archivos. Aquí hay un ejemplo (funciona en bash, pero no hay garantías para otros shells):
mvparents()
{
[[ $# -lt 2 ]] && echo "Usage: $0 [source] <source> ... [destination]." && return
# Get the destination directory.
for dest; do true; done
[[ ! -d "$dest" ]] && mkdir -p "$dest"
# Copy the arguments and remove the destination.
parameters=( "$@" )
unset parameters[${#parameters[@]}-1]
# For each source file: find, copy, delete.
for source in "${parameters[@]}"; do
if [ -r "$source" ]; then
find $(dirname $source) -name "$(basename $source)" -exec cp --parents {} $dest/ \; -delete
else
echo "$0: $source is not readable."
fi
done
}
Bueno... es un poco más largo de lo que esperaba pero debería funcionar.
Editar: comoSebastián PiechComo se señaló en un comentario, confiar en cp
hacer mv
el trabajo es un gran factor de destrucción del rendimiento, ya que mv
originalmente no es necesarioCopiarel archivo, simplemente edite sus metadatos. Es posible que desees reemplazar el bucle anterior con:
for source in "${parameters[@]}"; do
if [ -r "$source" ]; then
[[ ! -d "$dest/$(dirname $source)" ]] && mkdir -p "$dest/$(dirname $source)"
find $(dirname $source) -name "$(basename $source)" -exec mv {} "$dest/$(dirname $source)" \; -delete
else
echo "$0: $source is not readable."
fi
done
Sin embargo, dado que esto depende de unloteEn cuanto al valor de $PWD
, le pediría que tenga mucho cuidado si lo utiliza.