Como executar o equivalente mv de sim | cp -rf nos diretórios?

2

Usando a árvore de diretórios abaixo como exemplo, qual é a melhor maneira de mover o conteúdo de directory/folderA para directory .

Como sobrescrever um arquivo se existir um arquivo com o mesmo nome no destino, por exemplo: directory/folderA/2017/06/info.log e directory/2017/06/info.log .

directory
|-- folderA
|   |-- 2017
|   |   |-- 06
|   |
|   |-- 2016
|   |   |-- 12
|   |   |-- 11
|   |   |-- 10
|
|-- 2017
|   |-- 04
|   |-- 05
|   |-- 06
|
|-- 2016
|   |
    
por Greg 15.07.2017 / 04:07

2 respostas

4

Você pode conseguir isso com cp -l ( --link , arquivos de link físico em vez de copiar ):

cp -rfl folderA .
rm -rf folderA

O mv apenas se move, ou seja, renomeia o diretório para ser seu directory . Para mover arquivos dentro do mesmo sistema de arquivos mv usa rename() chamada do sistema. Se a origem e o destino estivessem em sistemas de arquivos diferentes, mv usaria cp e rm para realizar a mudança, mas ainda primeiro removeria o destino, copia arquivos vinculados com disco rígido ( -R ), mas não segue o simbólico links ( -P ):

rm -f destination_path && \
cp -pRP source_file destination && \
rm -rf source_file

Embora não seja possível alterar esse comportamento de mv , o comando cp é mais flexível e, na verdade, você deve usá-lo. Com cp , o -f causa a remoção e a criação de arquivos únicos dentro do destino, em vez de remover o destino inteiro primeiro.

O cp também é limitado, pois só pode sobrescrever ( -f ), preservador ( -n ) ou perguntar ( -i ). Se você precisar comparar os arquivos antes de decidir qual deles manter, precisará de rsync .

Se você ainda precisar usar a chamada de sistema rename() , mas cumprir sua meta de mesclar os diretórios conforme desejado, será necessário escrever um script que chame rename() s individual para arquivos únicos.

    
por 15.07.2017 / 08:00
1

Primeiro, criei sua árvore de diretórios com

[root@localhost /tmp]# mkdir -pv directory/folderA/2017/06 directory/folderA/2016/{10..12} directory/2017/{04..06} directory/2016

Em seguida, criei seus arquivos de exemplo com:

[root@localhost /tmp]# touch directory/{,folderA}/2017/06/info.log

Por fim, usei o rsync com o --delete-after para mover em vez do comportamento padrão do rsync, o que criaria uma cópia:

[root@localhost /tmp]# rsync --delete-after -a directory/folderA/ directory

Nota: o rastreio '/' após o diretório de origem (ou seja, diretório / pastaA / em oposição a diretório / pastaA) é necessário se você quiser que os diretórios sejam excluídos depois de serem copiados.

Claro, se você realmente quisesse digitar mv para obter o comportamento desejado, você poderia criar uma função de shell personalizada. Eu não estou defendendo isso, mas é possível. Desleixado, mas possível.

Aqui está uma função personalizada que você pode adicionar ao seu ~ / .bashrc:

function mv() {
    if [[ "$@" =~ .*--delete-after.*-av*.* ]]; then
            rsync $@
    else
            command mv $@
    fi; }

Em seguida, invoque o ~ / .bashrc atualizado, efetuando logout e login novamente em -ou- digitando:

[root@localhost /tmp]# exec bash

Agora você pode testar sua função personalizada com:

[root@localhost /tmp]# mv --delete-after -av directory/folderA/ directory

para obter resultados detalhados,

ou com:

[root@localhost /tmp]# mv --delete-after -a directory/folderA/ directory

para receber apenas erros, se algum for encontrado.

Como um aparte, você também pode evitar o piping sim para o comando cp -rf emitindo seu comando cp com uma barra invertida anterior como esta:

[root@localhost /tmp]# \cp -rf directory/folderA/* directory/

A razão pela qual você está canalizando sim é que você provavelmente tem um alias para o comando cp em seu ~ / .bashrc como este:

[root@localhost /tmp]# alias cp='cp -i'

que você pode verificar digitando:

[root@localhost /tmp]# type cp
    
por 22.07.2017 / 21:20