Como substituir um caracter por outro em todos os nomes de arquivos dos diretórios atuais?


41

Como você renomeia todos os arquivos / subdiretórios na pasta atual?

Digamos, eu tenho muitos arquivos e subdiretórios que estão com espaços e quero substituir todos os espaços por um sublinhado.

File 1
File 2
File 3
Dir 1
Dir 3

deve ser renomeado para

File_1
File_2
File_3
Dir_1
Dir_3

Respostas:


36

Se você precisar renomear arquivos também em subdiretórios e o seu findsuporte ao -execdirpredicado, poderá fazer

find /search/path -depth -name '* *' \
    -execdir bash -c 'mv -- "$1" "${1// /_}"' bash {} \;

Obrigado a @glenn jackman por sugerir uma -depthopção finde me fazer pensar.

Observe que em alguns sistemas (incluindo os GNU / Linux), findpode não conseguir encontrar arquivos cujo nome contenha espaços e também sequências de bytes que não formam caracteres válidos (normalmente, com arquivos de mídia com nomes com caracteres não ASCII codificados em um conjunto de caracteres diferente da localidade). Definir o código do idioma para C(como em LC_ALL=C find...) resolveria o problema.


Você precisaria usar find -maxdepth 1para fazer exatamente o que o OP pediu sobre como operar na pasta atual.
Caleb

11
Use a -depthopção find e você poderá se livrar do sort.
precisa saber é o seguinte

@ Jackman Jennifer: obrigado, agora eu entendo minha solução estava errada.
enzotib

2
Altere -name '* *'para -name '*_*'e mude "${1// /_}"para"${1//_/.}"
enzotib

11
@ kroiz: é chamado de "substituição de padrão". Você pode encontrá-lo na bashpágina do manual.
enzotib

34

Em qualquer shell, você pode fazer um loop sobre os arquivos cujo nome contém um espaço. Substituir os espaços por sublinhados é fácil no bash, ksh e zsh pela ${VARIABLE//PATTERN/REPLACEMENT}construção.

for x in *" "*; do
  mv -- "$x" "${x// /_}"
done

No Debian, Ubuntu e derivados, você pode usar o Perl rename(outras distribuições oferecem um programa diferente rename, e esse programa não é útil aqui).

rename 's/ /_/g' *

Uma solução zsh obrigatória:

autoload zmv
zmv '(*)' '${1// /_}'

Uma solução POSIX obrigatória:

for x in *" "*; do
  y=$(printf %sa "$x" | tr " " "_")
  mv -- "$x" "${y%a}"
done

O que significa o 'g' no final do comando "renomear"? Não o vi no manual.
JulianLai 15/01

Como renomear apenas o diretório? Não quero alterar o nome do arquivo.
JulianLai 15/01

@JulianLai s/…/…/gsignifica substituir todas as ocorrências. Não está muito bem explicado no manual . Se você quiser renomear diretórios, existem várias maneiras, procure-o (acho que já vi isso antes) e se você não conseguir encontrá-lo, faça uma nova pergunta.
Gilles 'SO- stop be evil'

grande ... isso me ajudou a mudar o nome de todos _MG_blah.JPGpara IMG_blah.JPG.
Abinash Dash

13

Você pode usar renamepara isso (aqui assumindo o de util-linux, não perlaquele):

cd /path/to/dir
rename ' ' _ *\ *

Isso encontrará todo o espaço de arquivos e diretórios no nome e substituirá o espaço por um sublinhado. Como ele usa a correspondência de arquivos glob, você precisa estar no diretório certo para começar.

Se você deseja fazer correspondências recursivas, é possível, mas pode ser necessário executar renamealgumas vezes para capturar quaisquer itens nos diretórios que foram renomeados:

cd /path/to/dir
shopt -s globstar
rename ' ' _ **/*\ *
!!; !!

2
renameRenomeará os arquivos especificados substituindo a primeira ocorrência de from em seu nome por para ”. Portanto, isso funcionará apenas para arquivos com um único espaço em seu nome. (Você pode ligar renameem loop, mas não é realmente a ferramenta certa aqui.)
Gilles 'SO- stop be evil'

2

Outra opção seria mmv, se instalado.

mmv \*\ \* \#1_#2

Isso muda apenas o primeiro espaço para um _, não funciona nomes com vários espaços.
Gilles 'SO- stop be evil'

Oups, você está certo. Desculpe pela confusão.
glglgl

1

No Debian / Ubuntu, com base nas respostas de Caleb e Gilles, foi o que funcionou para mim renomear arquivos recursivamente:

cd /path/to/dir
shopt -s globstar
rename 's/ /_/g' **

Nota: Para visualizar quais arquivos seriam renomeados e como, use a -nopção com rename:

rename -n 's/ /_/g' **

Outra nota: definindo globstarmarcas **corresponder arquivos em todos os subdiretórios, de modo que apenas o diretório atual é desejada, não globstar conjunto ou usar *, em vez de **.

Mais uma observação: O renamecomando precisa ser executado mais de uma vez para arquivos com várias ocorrências do termo de pesquisa.


Isso só funciona se os diretórios não contiverem espaços. (a renomeação de a b/c dpara a_b/c_dnão funcionaria, você precisaria primeiro renomear a b/c dpara a b/c_de depois a bpara a_b).
Stéphane Chazelas

@ Stephane: Isso significa executar o mesmo renamecomando duas vezes?
Markus Pscheidt

Bem, mais como quantas vezes há níveis aninhados de diretórios com espaços. Idealmente, você deseja percorrer primeiro a profundidade do diretório e converter apenas o nome de base do arquivo, como na solução aceita. Observe também que o bash **exclui arquivos de ponto e percorre links simbólicos.
Stéphane Chazelas

0

Se você não é um flash em expressões regulares (eu não sou!) E pode executar aplicativos projetados para o kde (você usa o kde - k desktop ou possui suas bibliotecas instaladas), o krename é um ótimo utilitário gráfico que permite ver o antes e o depois antes de se comprometer com as alterações. Ele tem várias transformações simples como opções e também suporta expressões regulares. Você pode até combinar várias transformações seqüenciais em uma única renomeação para não precisar projetar uma única transformação complexa que faça tudo de uma vez. Ele também tem uma opção para continuar renomeando os mesmos arquivos após a aplicação de uma renomeação.

Não o uso com tanta frequência, mas quando o faço, ele realmente realiza o trabalho com rapidez e facilidade. É realmente útil ao renomear vários arquivos de mídia baixados, para que você possa gerenciá-los uniformemente em seu sistema. Ajuda a baixar o manual do krename separadamente, para que você possa consultá-lo enquanto estiver usando o programa.

http://www.krename.net/

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.