Copiando todos os arquivos dentro de subdiretórios e renomeando em vez de sobrescrevendo

2

Eu tenho um número de imagens dentro de subdiretórios de outro diretório que eu gostaria de copiar em um único diretório para que todas as imagens fiquem no mesmo lugar.

Após um pouco de pesquisa, encontrei e modifiquei algumas coisas para criar este comando:

find . -name "z*.jpg" -exec cp '{}' ~/Extracted/ \;

Isso aparentemente funcionou, mas achei que as imagens com o mesmo nome seriam sobrescritas, então eu fiz isso:

find . -name "z*.jpg" -exec cp -n '{}' ~/Extracted/ \;

Mas agora as imagens com o mesmo nome são simplesmente ignoradas.

Existe alguma maneira que eu possa fazer isso para que todas as imagens sejam copiadas e imagens com o mesmo nome sejam renomeadas?

    
por barbaz 19.02.2013 / 17:21

2 respostas

4

O GNU cp(1) tem uma opção de backup:

cp --backup SOURCE [SOURCE...] [DESTINATION]

Isso tem os seguintes efeitos que podem ser controlados com outras opções, conforme descrito na página de manual de cp(1) :

--backup[=CONTROL]
          make a backup of each existing destination file

-b     like --backup but does not accept an argument

-S, --suffix=SUFFIX
          override the usual backup suffix

The backup suffix is ~, unless set with --suffix or SIMPLE_BACKUP_SUFFIX. The version control method may be selected via the --backup option or through the VERSION_CONTROL environment variable. Here are the values:

  • none, off: never make backups (even if --backup is given)
  • numbered, t: make numbered backups
  • existing, nil: numbered if numbered backups exist, simple otherwise
  • simple, never: always make simple backups

Exemplo

cp --backup=existing --suffix=.orig ~/Music/* ~/Videos

Isso copiará todos os arquivos em ~/Music para ~/Videos . Se um arquivo com o mesmo nome existir no destino, ele será renomeado anexando .orig ao seu nome como backup. Se houver um arquivo com o mesmo nome do backup, o backup será renomeado anexando .1 e, se houver, .2 e assim por diante. Só então o arquivo de origem é copiado para o destino.

Se você deseja copiar arquivos em subdiretórios, use recursivamente -R :

cp -R --backup=existing --suffix=.orig ~/Music ~/Videos
    
por 19.10.2014 / 13:59
2

Seu problema é, na verdade, encontrar uma variante cp que cria o arquivo de destino com um nome diferente, se já existir. Eu não estou ciente de uma ferramenta que faz isso, no entanto, não é difícil implementar você mesmo:

#!/bin/bash
cp -vn "$1" "$2"/ || cp -vn "$1" "$2"/"${1##*/}"~"$(md5sum "$1" | cut -f1 -d' ')"

Esse script chama cp novamente no caso de falha, anexando a soma de verificação ao nome do arquivo. Falha: Se um terceiro arquivo com o mesmo nome aparecer, ele sobrescreverá o segundo arquivo se eles forem idênticos .

Dado que o script acima é chamado saveCopy e armazenado no diretório de trabalho pai, o seguinte funciona:

$ find . -name 'z*.jpg' -exec ./saveCopy {} /tmp/Extracted/ \;
./a/z1.jpg -> /tmp/Extracted/z1.jpg
./a/z2.jpg -> /tmp/Extracted/z2.jpg
./a/z3.jpg -> /tmp/Extracted/z3.jpg
/tmp/Extracted/z3.jpg not overwritten
./b/z3.jpg -> /tmp/Extracted//z3.jpg~d41d8cd98f00b204e9800998ecf8427e
./b/z4.jpg -> /tmp/Extracted/z4.jpg

Esteja ciente de que o script só funciona para um único arquivo de entrada e se o destino é um diretório! Pode certamente ser melhorado; -)

    
por 19.02.2013 / 18:28

Tags