mv e hierarquia de diretórios cp? [duplicado]

4

Também posso mover ou copiar a hierarquia de diretório 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?

    
por Tim 09.10.2014 / 14:58

1 resposta

9

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.

    
por 09.10.2014 / 15:05