Renomeia arquivos em diretórios diferentes com o mesmo nome, então cada um tem um nome único (numerado)

3

Eu preciso renomear os arquivos no meu cartão SD, para poder copiar o conteúdo de várias subpastas para o meu disco rígido. Primeiro eu preciso encontrá-los por sua extensão .MOD (eu posso fazer isso usando find ./path/*.MOD2 , como eles estão em diretórios diferentes).

Eu preciso renomeá-los porque todos eles têm nomes como MOV001.MOD , MOV002.MOD , em outro diretório há outros vídeos, mas com nomes semelhantes. Isso foi criado pela minha câmera. Após a renomeação, eu poderia copiá-los por um comando para o meu disco rígido.

Por causa de seus nomes reais, quando uso cp ./path/*.MOD new-path , o resultado seria sobrescrever arquivos com nomes semelhantes.

Como posso resolver isso?

    
por Mikulas Kuzmiak 07.11.2016 / 19:47

2 respostas

3

Este pequeno script renomeia os arquivos sem movê-los

n=0; for files in dir1/*.MOD dir2/*.MOD dir3/*.MOD; do printf -v new "${files/MOV*./%02d.}" "$((++n))"; echo mv -v "$files" "$new"; done

ou mais legível:

#!/bin/bash
n=0
for files in dir1/*.MOD dir2/*.MOD dir3/*.MOD; do
   printf -v new "${files/MOV*./%02d.}" "$((++n))"
   echo mv -v -- "$files" "$new"
done

Substitua dir1 etc pelos caminhos reais para seus diretórios com os arquivos

Remova echo (é só para testar) depois de verificar se isso fornece o que você deseja, para realmente renomear os arquivos.

Isso contém os arquivos 01.MOD , 02.MOD , etc. Se você tiver mais de 99 arquivos, substitua %02d por %03d para obter 001.MOD etc

Explicação:

n=0 Isso apenas define n como 0 , que é onde eu quero que o bash comece a contar.

for files in dir1/*.MOD dir2/*.MOD dir3/*.MOD

Um loop for pode executar comandos iterativamente em cada arquivo por vez. A sintaxe é for [variable] in [these things I want to do something to] ; do [command(s)] $[variable]; done , chamei a variável files e encontrei seus arquivos usando um glob: *.MOD é expandido pelo shell para qualquer arquivo cujo nome termine em .MOD ( * corresponde a qualquer caractere)

printf -v new

printf pode formatar os novos números com uma largura fixa para facilitar a classificação. new é outra variável - este é o novo nome dos arquivos.

"${files/MOV*./%02d.}" "$((++n))"

Referenciando a variável files do anterior e substituindo MOV* (lembre-se * de qualquer caractere) com o resultado do número incremental $((++n)) (isso é n da primeira linha do script, vá por um de cada vez que o loop é executado em um arquivo) formatado usando o código %02d que para printf significa um número decimal de uma largura fixa de dois dígitos 01, 02 etc. O padrão de pesquisa e substituição inclui o . para parar * correspondendo ao nome do arquivo inteiro e, assim, removendo a extensão.

echo mv -v -- "$files" "$new"

Eu adiciono o echo apenas para testes - isso mostra o que será feito em vez de realmente fazê-lo. Remova o eco quando estiver satisfeito com o resultado para realmente executar o comando.

mv renomeia ou move arquivos; sua sintaxe é mv oldname newname . Eu adicionei o -v sinalizador que diz mv para ser "detalhado" e relatar cada ação. Eu adicionei -- apenas para estar seguro - isso diz mv para não aceitar mais opções, o que impede que qualquer nome de arquivo começando com - seja interpretado como opções para o comando - não é necessário no seu caso, mas uma boa prática.

Cada arquivo especificado pela variável files é mv ed para um nome exclusivo criado na variável new . Usamos $ para fazer referência a variáveis e elas devem estar em "aspas duplas" para evitar que o shell faça outras expansões nos nomes de arquivos - isso impede que caracteres especiais ou espaços em nomes de arquivos causem problemas.

    
por Zanna 07.11.2016 / 20:42
1

Você pode copiá-los de um diretório recursivo (incluindo todos os subdiretórios), procurar por extensão e renomeá-los em uma única etapa com o script abaixo.

Extraído de scripts que eu uso para garantir que não substituam arquivos, ao copiá-los de um diretório recursivo:

#!/usr/bin/env python3
import os
import shutil
import sys

dr = sys.argv[1]
new_dir = sys.argv[2]

for root, dirs, files in os.walk(dr):
    for name in files:
        if name.lower().endswith(".mod"): # for your extension
            n = 1; name_orig = name
            while os.path.exists(new_dir+"/"+name):
                name = "duplicate_"+str(n)+"_"+name_orig
                n = n+1
            newfile = new_dir+"/"+name
            shutil.copy(root+"/"+name_orig, newfile)

Copie o script em um arquivo vazio, salve-o como nodupes.py , execute-o com o diretório input (source-) e output como argumentos:

python3 /path/to/nodupes.py /path/to/sourcedir /path/to/outputdir

Ele renomeia arquivos com nomes semelhantes, como:

Claro que, em vez de duplicate_ , o script pode ser alterado para usar qualquer coisa numerada (ou apenas números).

Uma versão generalizada, não pesquisando apenas uma extensão, seria:

#!/usr/bin/env python3
import os
import shutil
import sys

dr = sys.argv[1]
new_dir = sys.argv[2]

for root, dirs, files in os.walk(dr):
    for name in files:
        n = 1; name_orig = name
        while os.path.exists(new_dir+"/"+name):
            name = "duplicate_"+str(n)+"_"+name_orig
            n = n+1
        newfile = new_dir+"/"+name
        shutil.copy(root+"/"+name_orig, newfile)
    
por Jacob Vlijm 07.11.2016 / 20:32