Também posso mover ou copiar a hierarquia de diretórios de um arquivo quando eu mv
ou cp
o arquivo?
Por exemplo, se eu mv
ou cp
dir1/dir2/file
em outro lugar, será apenas mv
ou cp
file
. E se eu quiser também mv
ou cp
dir1/dir2
? Em vez de mkdir -p dir1/dir2
, isso pode ser feito com um comando?
Responder1
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 possui uma --parents
opção, mas você poderia fazer algo como:
$ find step1/step2/step3 -name "file" -exec cp --parents {} copy/ \; -delete
O que irá:
- Encontre o arquivo.
- Copie-o (junto com seus pais) para o destino.
- Exclua o original.
Você poderia 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 longo do que eu esperava, mas deve funcionar
Editar: comoSebastião Piechapontado em um comentário, confiar no trabalho de cp
to mv
do é um grande destruidor de desempenho, já que mv
originalmente não precisacópia deo arquivo, basta editar 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, uma vez que esta coisa depende de ummuitosobre o valor de $PWD
, peço que você tenha muito cuidado ao usá-lo.