Você pode usar a opção 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
, no entanto, não tem um --parents
, mas você pode fazer algo como:
$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete
Qual será:
- Encontre o arquivo.
- Copie (junto com seus pais) para o destino.
- Exclua o original.
Você pode criar uma função para isso:
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/
Isso pode exigir alguns ajustes se você tentar mover vários arquivos. Aqui está um exemplo (trabalhando no bash, mas sem garantias para outros 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
}
Bem ... isso é um pouco mais do que eu esperava, mas deveria fazer o trabalho
Editar: como Sebastian Piech apontou em um comentário, confiando em cp
to do% O trabalho demv
é um matador de desempenho, já que mv
originalmente não precisa copiar o arquivo, apenas edite seus metadados. Você pode querer substituir o loop acima por:
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
No entanto, como essa coisa depende de um lote no valor de $PWD
, peço que seja muito cauteloso caso você a use.