hierarquia de diretórios mv e cp?

hierarquia de diretórios mv e cp?

Também posso mover ou copiar a hierarquia de diretórios de um arquivo quando eu mvou cpo arquivo?

Por exemplo, se eu mvou cp dir1/dir2/fileem outro lugar, será apenas mvou cp file. E se eu quiser também mvou cp dir1/dir2? Em vez de mkdir -p dir1/dir2, isso pode ser feito com um comando?

Responder1

Você pode usar a opção cpde --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 --parentsopçã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 cpto mvdo é um grande destruidor de desempenho, já que mvoriginalmente 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.

informação relacionada