Desfazer ação do comando copy (cp)

12

Copiei alguns arquivos da pasta de origem para a pasta de destino usando a linha de comando abaixo no terminal.

sudo cp From_SOURCE/* To_DESTINATION/

Agora quero desfazer esse comando.

    
por αғsнιη 10.08.2014 / 17:19

3 respostas

13

Se eu entendi bem, o seguinte é o caso:

  • Você copiou um número (presumivelmente grande) de arquivos para um diretório existente e precisa / deseja reverter a ação.
  • O diretório de destino contém um número de outros arquivos, que você precisa manter lá, o que torna impossível simplesmente remover todos os arquivos do diretório

O script abaixo procura no diretório original (fonte) e lista esses arquivos. Em seguida, ele procura no diretório para o qual você copiou os arquivos e remove apenas os arquivos listados, como eles existem no diretório de origem.

O elemento try é adicionado para evitar erros, por exemplo, no caso de você já ter removido alguns arquivos manualmente ou se nem todos os arquivos do diretório de origem foram copiados para o destino. Se você precisar de privilégios sudo, simplesmente execute o script com "sudo" (veja abaixo).

O script

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for root, dirs, files in os.walk(source_dir):
    for name in files:
        try:
            os.remove(target_folder+"/"+name)
        except FileNotFoundError:
            pass

Como usar

  • Cole o script em um arquivo vazio, salve-o como reverse.py ,
  • Insira os caminhos corretos para a pasta de origem e destino,
  • Torne-o executável por conveniência,
  • Execute-o pelo comando:

    [sudo] /path/to/reverse.py
    

Aviso

Primeiro, tente um diretório de teste se eu entendi bem o que você precisa alcançar!

Se o diretório de origem for "plano"

Caso o diretório de origem não tenha subdiretórios, o script pode até ser mais simples:

#!/usr/bin/env python

import os

source_dir = "/path/to/source" # the folder you copied the files from
target_folder = "/path/to/destination" # the folder you copied the files to

for file in os.listdir(source_dir):
    try:
        os.remove(target_folder+"/"+file)
    except FileNotFoundError:
        pass

Nota

Se a ação de cópia sobrescreveu (substituído) um arquivo de nome similar no destino, o arquivo será removido, mas o arquivo original (obviamente) não será trazido de volta pelo script. A suposição é que não há confrontos de nomes.

    
por Jacob Vlijm 10.08.2014 / 19:13
6

TL; DR:

Todos os arquivos que estão presentes em src e dest podem ser removidos de dest da seguinte forma:

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;

Para uma explicação passo-a-passo, veja abaixo.

Simplificando o problema:

Para entender o que o comando que queremos desfazer, começamos simplificando:

O comando que queremos desfazer é

sudo cp From_SOURCE/* To_DESTINATION/

Para entender como desfazer, sudo não é relevante.

Usarei os nomes dos diretórios src para From_SOURCE e dest para To_DESTINATION .

Agora, nosso comando é:

cp src/* dest/

Se src contiver os arquivos f1 , f2 e f3 e os diretórios d1 e d2 , o shell expandirá esse comando para:

cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/

Sem opções como -r , -R ou -a , o comando cp não copia diretórios.
Isso significa que o comando os deixará de fora, mostrando um erro para cada um deles:

$ cp src/f1 src/f2 src/f3 src/d1 src/d2 dest/
cp: omitting directory 'src/d1'
cp: omitting directory 'src/d2'

Isso significa que copiamos apenas arquivos simples e nenhum diretório para dest .

Decidindo quais arquivos serão removidos:

Possivelmente havia arquivos em dest do mesmo nome que os arquivos em src . Neste caso, os arquivos foram sobrescritos (1). É tarde demais para eles, desculpe. Recupere-os do último backup.

Em relação aos arquivos que estão lá, queremos remover apenas os arquivos que foram copiados. Esses arquivos existem nos dois diretórios, com o mesmo nome e o mesmo conteúdo.

Então, procuramos por esses arquivos:

Primeiro, nós cd into src , porque ele torna os seguintes comandos find muito mais simples e definimos uma variável como o caminho absoluto do dest:

$ cd src
$ destdir="$(readlink -f dest)"

Em seguida, listamos todos os arquivos em src:

$ find . -maxdepth 1 -type f

e, para cada arquivo encontrado, use cmp para verificar se existe um arquivo com o mesmo conteúdo em dest:

$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -print

Removendo os arquivos com cuidado:

Esses arquivos são os que queremos remover. Mas, com certeza, nós os movemos para um diretório diferente primeiro - e dê uma olhada nos comandos antes de executá-los:

$ toDelete=/tmp/toDelete ; mkdir -p "$toDelete"
$ find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec echo mv -n "$destdir/{}" "$toDelete"/ \;
mv -n /path/to/dest/./f1 /tmp/toDelete/'
mv -n /path/to/dest/./f2 /tmp/toDelete/'
mv -n /path/to/dest/./f3 /tmp/toDelete/'

Parece bom! Agora podemos deixar de fora o echo para executar os comandos mv reais:

find . -maxdepth 1 -type f -exec cmp -s '{}' "$destdir/{}" \; -exec mv -n "$destdir/{}" "$toDelete"/ \;

Todos os arquivos de dest que foram copiados de src e, na verdade, são os mesmos em src e dest , agora estão em /tmp/toDelete/ e podem ser removidos depois de dar uma última olhada. / p>

Notas:
(1) Verifique se cp é um alias para cp -i ou mais, o que evitaria a substituição de arquivos perguntando primeiro.

    
por Volker Siegel 11.08.2014 / 01:21
4

Isso é antigo, mas eu só queria postar uma resposta pura:

Primeiro, mude para o diretório em que você copiou os arquivos.

cd dest

Em seguida, ls do diretório de origem e canalize a saída em rm

ls source | xargs rm

    
por Michael Goldstein 16.07.2016 / 23:43