Substitui uma palavra em um nome de diretório e nos nomes de arquivos naquele diretório

7

Eu tenho uma estrutura de diretórios como esta:

Bookname Edition 1
  Bookname Edition 1 type1.pdf
  Bookname Edition 1 type2.pdf
Bookname Edition 2
  Bookname Edition 2 type1.pdf
  Bookname Edition 2 type2.pdf

Eu quero alterar de forma recursiva o nome de Edition para Volume do diretório e dos nomes de arquivos nesses diretórios.

Eu comecei com isso e tudo bem se eu estou no diretório:

for f in *.pdf; do
    a="$(echo $f | sed s/Edition/Volume/)"
    mv "$f" "$a"
done

Então eu tentei isso para mudar todos os arquivos sob os diretórios, e é aí que eu fiquei preso ...

Por favor, você pode me dizer como fazer isso ou me dar uma maneira melhor de fazer isso. Existem 15000 PDFs em 100 diretórios.

    
por Bishop 22.01.2018 / 21:54

4 respostas

11

Se sua estrutura tiver apenas dois níveis, você não precisará recursionar.

Não analise nomes de arquivos com sed . Se você quiser usar a sintaxe regex e sed style para renomear arquivos, use rename . Se você está usando o Ubuntu 17.10, você precisa instalá-lo

sudo apt install rename

Então você pode usar resposta do pa4080 .

Com rename , use a opção -n para testes.

rename -n 'expression' file(s)

Você também pode usar apenas o comando mv . Como um comando de uma linha:

for d in ./*/; do mv -v "$d" "${d/Edition/Volume}"; done; for f in ./*/*; do mv -v "$f" "${f/Edition/Volume}"; done

Você pode usar echo para testes com mv , ou seja, echo mv -v source dest , mas fornece resultados imprecisos aqui, a menos que você teste e execute os loops separadamente.

Como um script:

#!/bin/bash

# rename directories first
for d in ./*/; do
    mv -v "$d" "${d/Edition/Volume}"
done

# now rename files
for f in ./*/*; do
    mv -v "$f" "${f/Edition/Volume}"
done

mv e rename reconhecem -- para indicar o final das opções. Como todos os caminhos começam com ./ neste exemplo, não precisamos usar isso, mas se os caminhos puderem começar com - , use -- no final das opções, por exemplo, rename -n -- 's/foo/bar/' * , para evitar esses caminhos sendo interpretado como opções.

    
por Zanna 22.01.2018 / 23:16
6

Você pode usar o comando rename duas vezes para realizar essa tarefa:

rename 's/Edition/Volume/' */        # rename the directories
rename 's/Edition/Volume/' */*.pdf   # rename the PDF files inside

Aqui estão duas perguntas semelhantes:

por pa4080 22.01.2018 / 23:15
5

Em diretórios de vários níveis, você pode fazer isso em uma etapa, mas o problema é que você precisa renomear os diretórios de baixo para cima, para evitar que o comando ou script altere o nome do diretório antes de seu conteúdo Mudou.

Em python, você pode usar:

os.walk

em combinação com

topdown=False

Em um script:

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

for root, dirs, files in os.walk(sys.argv[1], topdown=False):
    for f in files:
        shutil.move(
            root+"/"+f, root+"/"+f.replace("Edition", "Volume").strip()
        )
    for dr in dirs:
        shutil.move(
            root+"/"+dr, root+"/"+dr.replace("Edition", "Volume").strip()
        )

Salve o script como change_name.py , execute-o com o diretório como argumento:

python3 /path/to/change_name.py <directory>

Isso funciona recursivamente em qualquer número de níveis.

    
por Jacob Vlijm 22.01.2018 / 23:39
1

Use find com a opção -depth combinada com prename :

find [DIRS...] -depth | prename -n 's|Edition(?=[^/]*$)|Volume|'

Explicação:

  • -depth seleciona os filhos do diretório antes dos pais. Uma ferramenta "consumindo" os nomes de caminho selecionados para renomear pode renomear os filhos antes de seus pais.

  • s|Edition(?=[^/]*$)|Volume| substitui a primeira ocorrência de Edition no nome do caminho por Volume , mas somente se o restante não contiver / , i. e. aplica-se apenas ao último componente do nome do caminho (obtido pela antecipação positiva (?=[^/]*$) ).

  • -n diz a prename para não renomear os caminhos, mas para imprimir como eles seriam renomeados. Remova essa opção para renomeá-la.

por David Foerster 11.02.2018 / 12:23