Troque duas strings separadas por um símbolo em vários nomes de arquivos de um diretório

Troque duas strings separadas por um símbolo em vários nomes de arquivos de um diretório

Quero alterar uma string como author - namenos nomes de arquivos de alguns livros para name - author. Estou tentando

ls * | sed -r 's/(.+) - (.+).pdf/mv \2 - \1.pdf/' | sh

Talvez seja uma mistura de Alternar duas strings de comprimento arbitrário separadas por um símbolo eRenomeie vários arquivos com sed

Isso não funciona

for file in *; do mv "$file" "$(echo "$file" | sed -r 's/(.+) - (.+).pdf/\2 - \1.pdf/')"

Nem

rename 's/\([.]+\) - \([.]+\)\.pdf/\2 - \1\.pdf/' *

Isso funciona

rename 's/(.+) - (.+).pdf/\2 - \1.pdf/' *

Responder1

Experimente isso

% ls -1                                                                                                       
001-foobar.pdf
002-foobar.pdf
003-foobar.pdf

Código

% rename -n 's/([^-]+)-([^\.]+)\.pdf/$2-$1.pdf/' *.pdf                                                          
001-foobar.pdf -> foobar-001.pdf
002-foobar.pdf -> foobar-002.pdf
003-foobar.pdf -> foobar-003.pdf

Observação

(remova a opção -n quando seus testes estiverem OK)

aviso Existem outras ferramentas com o mesmo nome que podem ou não fazer isso, então tome cuidado.

Se você executar o seguinte comando ( GNU)

$ file "$(readlink -f "$(type -p rename)")"

e você tem um resultado como

.../rename: Perl script, ASCII text executable

e não contendo:

ELF

então esta parece ser a ferramenta certa =)

Caso contrário, para torná-lo o padrão (geralmente já é o caso) em uma Debianderivada como Ubuntu:

$ sudo update-alternatives --set rename /path/to/rename

(substitua /path/to/renamepelo caminho do seu perl's renamecomando.


Se você não possui este comando, procure em seu gerenciador de pacotes para instalá-lo oufaça isso manualmente


Por último, mas não menos importante, esta ferramenta foi originalmente escrita por Larry Wall, o pai do Perl.

Responder2

Presumo que os nomes dos arquivos sigam o padrão author - name.pdfe que ambos authorpossam nameconter qualquer caractere válido, exceto -cercado por espaços.

find . -type f -name '* - *.pdf' \
    -execdir sh -c 'b=${1% - *}; e=${1#* - }; mv "$1" "${e%.pdf} - $b.pdf"' sh {} \;

Isso localiza todos os arquivos regulares no diretório atual que possuem nomes que correspondem ao padrão * - *.pdf.

Para cada arquivo, um subshell é executado. O subshell faz o seguinte:

b=${1% - *}  # pick out the start of the filename
e=${1#* - }  # pick out the end of the filename

# Combine $b and $e into a new filename while removing ".pdf" from
# the end of the original filename and adding it to the end of
# the new filename instead.
mv "$1" "${e%.pdf} - $b.pdf"

Testando:

$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Aug 30 11:31 arr! - Boaty McBoatface.pdf
-rw-r--r--  1 kk  wheel  0 Aug 30 11:30 hello world - bingo-night!.pdf

$ find . -type f -name '* - *.pdf' -execdir sh -c 'b=${1% - *}; e=${1#* - }; mv "$1" "${e%.pdf} - $b.pdf"' sh {} \;

$ ls -l
total 0
-rw-r--r--  1 kk  wheel  0 Aug 30 11:31 Boaty McBoatface - arr!.pdf
-rw-r--r--  1 kk  wheel  0 Aug 30 11:30 bingo-night! - hello world.pdf

Executá-lo novamente trocaria os nomes de volta aos originais.

informação relacionada