Use find + sed + cp para localizar arquivos e copiá-los para um diretório com um nome diferente

2

Estou tentando copiar vários arquivos nomeados folder.jpg para uma pasta. O problema é que todos os arquivos são nomeados da mesma forma, eu preciso renomeá-los no processo. Eu sei que provavelmente posso fazê-lo com sed mas eu gostaria de renomeá-los para o nome de parte da pasta pai. Aqui está o que eu tenho apenas para encontrar e copiar os arquivos

cp $(find . -iname "folder.jpg") .albumart/

A estrutura da pasta é ./artist/artist.year.album/folder.jpg e o que eu gostaria de usar a pasta pai (ou apenas parte dela) para nomear o arquivo. Alguém pode me ajudar com um forro para realizar a tarefa? Para tornar as coisas ainda mais complicadas, algumas pastas têm mais um nível de CD1 e CD2 que eu gostaria de ignorar se estiverem presentes (por exemplo, ./artist/artist.year.album/CD1/folder.jpg)

    
por Rothgar 04.02.2013 / 18:52

4 respostas

5

Supondo que você tenha bash , esta versão simplesmente usa sua estrutura de pastas (por exemplo, ./foo/bar/baz/folder.jpg ) e substitui todas as barras por sublinhados (por exemplo, você recebe foo_bar_baz_folder.jpg ):

find . -iname folder.jpg -exec bash -c 'for x; do x=${x#./}; cp -i "$x" ".albumart/${x//\//_}"; done' _ {} +

Observe que, não importa o que você faça, sempre que mover arquivos de vários locais para o mesmo destino, há sempre uma chance de uma colisão de nomes.

    
por 04.02.2013 / 19:12
3

Com zsh:

autoload zmv
zmv -n -C '(**/)folder.jpg' '.albumart/${1:t}.jpg'

Remova -n quando estiver feliz.

Esse evitará colisões de nomes (falhará com um erro se duas substituições resolverem o mesmo nome) como:

$ zmv -n -C '(**/)folder.jpg' '.albumart/${1:t}.jpg'
zmv: error(s) in substitution:
b/c/folder.jpg and a/b/c/folder.jpg both map to .albumart/c.jpg
    
por 04.02.2013 / 20:04
1

Não analise a saída de find . Isso será interrompido se houver espaços em branco ou caracteres glob ?*\[ em nomes de arquivos. Se você usar find , faça-o chamar o comando com a ação -exec . Chame um shell na ação -exec para executar as transformações de string necessárias.

find -name folder.jpg -exec sh -c '
    dir=${0%/*}      # stip off the file name
    case $dir in */CD[0-9]) dir=${dir%/*};; esac
    cp -ip "$0" ".albumart/${dir##*/}.jpg"
' {} \;

O zmv do Zsh é muitas vezes a maneira mais fácil de fazer esse tipo de cópia .

zmv -C -o-p -w '**/*.jpg' '.albumart/${${${1%/}/CD<->}##*/}.jpg'

Algumas explicações:

  • A sintaxe geral é zmv OPTIONS… SOURCE_PATTERN REPLACEMENT .
  • -w ativa a correspondência de grupo curinga. No texto de substituição, $1 refere-se à parte correspondida por **/ (com um% final/ a menos que o texto correspondente esteja vazio, ou seja, o arquivo esteja no diretório superior) e $2 à parte correspondida por * em *.jpg .
  • Tanto o padrão quanto o texto de substituição devem ser protegidos contra expansão: eles precisam ser passados literalmente para zmv .
  • Para entender ${${${1%/}/CD<->}##*/} , leve de dentro para fora. Primeiro, pegue $1 . Retire um/ final (se houver). Retire um padrão final correspondente a /CD<-> , se houver (um <-> corresponde a um ou mais dígitos). Finalmente fora de tudo, menos o último componente do diretório.
  • Se você deseja substituir espaços por sublinhados, adicione mais uma camada de expansão de parâmetro : ${${${${1%/}/CD<->}##*/}// /_} .
por 05.02.2013 / 02:26
0

Obviamente, atrasado com esta resposta, mas esperando que alguns outros possam achar útil.

for i in $(find . -type f -iname "folder.jpg" -printf "%P\n") ; do t=$(echo $i | sed 's|/|\.|g'); cp $i TARGETDIR/$t ; done

O -printf "%P\n" é para retirar a% principal./ da saída de find .

Registre o resultado find ( $i ) em sed e faça alterações, nesse caso sed substitui / por . e atribua o valor dessa coisa inteira a t

Em seguida, basta copiar o arquivo encontrado por find , $i neste caso, para o TARGETDIR com o novo nome $t .

Encontrado: ./artist/artist.year.album/folder.jpg
Rendimento: TARGETDIR/artist.artist.year.album.folder.jpg

Espero que isso ajude alguém lá fora.

    
por 03.05.2017 / 23:28

Tags