Como renomear todos os arquivos com caracteres especiais e espaços em um diretório?


10

Como posso renomear todos os arquivos em um diretório específico em que os arquivos contêm espaços em branco e caracteres especiais ($ e @) em seus nomes?

Tentei o renamecomando da seguinte maneira para substituir todos os espaços e caracteres especiais por um _:

$ ls -lrt
total 464
-rwxr-xr-x. 1 pmautoamtion pmautoamtion 471106 Jul 17 13:14 Bharti Blocked TRX Report Morning$AP@20150716.csv


$ rename -n 's/ |\$|@/_/g' *
$ ls -lrt
total 464
-rwxr-xr-x. 1 pmautoamtion pmautoamtion 471106 Jul 17 13:14 Bharti Blocked TRX Report Morning$AP@20150716.csv
$

O comando funciona, mas não fará nenhuma alteração nos nomes dos arquivos e também não retornará nenhum erro. Como resolver isso e também existem outras maneiras?


1
Você pode estar esperando o script perl rename (ref: manpages.ubuntu.com/manpages/dapper/man1/prename.1.html ), mas está recebendo a renomeação do util-linux, que não funciona da mesma maneira.
Jeff Schaller

Respostas:


10

A -nbandeira é para

- sem ação

Nenhuma ação: mostre quais arquivos teriam sido renomeados.

Portanto, é normal se você não tiver nenhuma alteração.

Em relação ao seu comando, ele está funcionando para mim:

$ touch "a @ test"
$ ls
a @ test
$ rename -n 's/ |\$|@/_/g' *
a @ test renamed as a___test

Talvez, dependendo do seu shell, você precise escapar do |

$ rename -n 's/ \|\$\|@/_/g' *

Ou você pode usar a […]notação para agrupar caracteres:

$ rename -n 's/[ @\$]/_/g' *

1
Eu tentei todos os três sem a opção -n e ainda assim não mudará o nome do arquivo. Não dou nenhum erro para nenhum dos três tipos mencionados acima. Talvez o comando renomear não funcione por algum motivo. Existe alguma outra maneira de alterar todos os arquivos em um diretório com espaços ou $ ou @ em seus nomes?
Ankit Vashistha

@AnkitVashistha rename -n 's/./_/g' *produz alguma coisa?
Fredtantini 17/07/2015

Não dá nada, nenhuma saída, nenhum erro. Apenas aterra na próxima linha de comando.
Ankit Vashistha

renomear também não está funcionando para eu substituir (espaço) ou ':' no Ubuntu 18.04, Bash 4.4.20 (1) -release
Ouss 14/02

7

Você pode tentar assim:

for file in ./*Block*                                       
do echo mv "$file" "${file//[ ()@$]/_}"
done

Se você estiver satisfeito com o resultado, remova o echoantes mvpara renomear os arquivos.


Uma das melhores soluções pelas quais passei, estava tentando por isso há tanto tempo
Sushin Pv

2

procurando um script bonito para remover caracteres especiais e caracteres especiais alemães, substituindo-os por universais para não remover informações úteis Atualizei a última versão do script, que teve alguns problemas menores, resultando em:

#!/bin/bash

for file in ./*
do
  infile=`echo "${file:2}"|sed  \
         -e 's|"\"|"\\"|g' \
         -e 's| |\ |g' -e 's|!|\!|g' \
         -e 's|@|\@|g' -e 's|*|\*|g' \
         -e 's|&|\&|g' -e 's|]|\]|g' \
         -e 's|}|\}|g' -e 's|"|\"|g' \
         -e 's|,|\,|g' -e 's|?|\?|g' \
         -e 's|=|\=|g'  `
  outfileNOSPECIALS=`echo "${file:2}"|sed -e 's|[^A-Za-z0-9._-]|_|g'`
  outfileNOoe=`echo $outfileNOSPECIALS| sed -e 's|ö|oe|g'`
  outfileNOae=`echo $outfileNOoe| sed -e 's|ä|ae|g'`
  outfileNOue=`echo $outfileNOae| sed -e 's|ü|ue|g'`
  outfileNOOE=`echo $outfileNOue| sed -e 's|Ö|OE|g'`
  outfileNOAE=`echo $outfileNOOE| sed -e 's|Ä|AE|g'`
  outfileNOUE=`echo $outfileNOAE| sed -e 's|Ü|UE|g'`
  outfileNOss=`echo $outfileNOUE| sed -e 's|ß|ss|g'`
  outfile=${outfileNOss}
  if [ "$infile" != "${outfile}" ]
  then
        echo "filename changed for " $infile " in " $outfile
        mv "$infile" ${outfile}
  fi
done

exit

resultando em:

insira a descrição da imagem aqui

@don_crissti: Ele está fazendo o hokus-pokus com o infile, já que o linux tem seus próprios problemas ao lidar com caracteres especiais ao mover o nome do arquivo.


1
caracteres especiais ? quais ?
don_crissti 22/02

Espaço, Símbolo, E comercial ... #
Matthias R. Wiora

Não há problema em mover um arquivo com um nome que contenha caracteres especiais (incluindo uma nova linha) ... Você provavelmente não está familiarizado com os shells (e btw, isso não tem nada a ver com linux, é um recurso de shell ... )
don_crissti 22/02

mh tudo bem - você talvez direita
Matthias R. Wiora

1

Como o renamecomando não funcionou para mim por motivos desconhecidos e não recebo outras respostas para minha pergunta, tentei fazer um esforço para tornar a renomeação possível. Essa pode não ser a melhor abordagem para renomear os arquivos, mas funcionou para mim e é por isso que eu gostaria de publicá-la como resposta, para que, se alguém mais ler isso, obtenha ajuda para alterar os nomes dos arquivos da maneira que eu fiz.

Agora, para mim, eu sei que todos os arquivos terão um texto específico em seus nomes, que é a palavra "Bloquear". A seguir, estão os nomes dos arquivos antes de sua renomeação ser concluída:

anks@anks:~/anks$ ls -lrt
total 4
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block Report$AP@12Jul15.csv
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block Report$HP@12Jul15.csv
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block Report$CH@12Jul15.csv
-rw-r--r-- 1 anks anks   0 Jul 25 14:47 Bharti TRX Block Report$KK@12Jul15.csv
-rw-r--r-- 1 anks anks   0 Jul 25 14:48 Bharti TRX Block Report$UW@12Jul15.csv

Agora eu escrevi um pequeno script de shell para tornar isso possível. A seguir está o código:

#!/bin/bash

PATH="/home/ebfijjk/anks"

# Put the old filenames in a file.
ls $PATH | grep Block >> oldValues

# Put the new names without " " or "@" or "$" in another file
cat oldValues | sed 's/\$/_/g' | sed 's/\@/_/g' | sed 's/ /_/g' >> newValues

# Create a new file with Old names and New names seperated by a #.
paste -d'#' oldValues newValues >> oldAndNew

# Read the file with both old and new names and rename them with the new names.
while IFS='#'; read oldValue newValue
do
    mv "$oldValue" "$newValue"

done < oldAndNew

rm oldValues newValues oldandNew

E é isso, quando executo o script, ele renomeia todos os nomes de arquivos com espaços em branco ( ) ou $ou @com _esses caracteres.


você pode substituir cat foo | sed S1 | sed S2 | sed S3 >> barporsed -e S1 -e S2 -e S3 foo >> bar
Archemar

2
@Archemar - ou simplesmente sed 's/[ ()@$]/_/g'oused 'y/ ()@$/_____/'
don_crissti

Obrigado don_crissti e Archemar por seus comentários e sugestões.
Ankit Vashistha

1

Este apenas tira os caracteres especiais dos nomes de arquivos

for file in *; do mv "$file" `echo $file | tr -cd '.A-Za-z0-9_-'` ; done
Námásté Egész-ség.mkv --> NmstEgsz-sg.mkv

colocar echodepois ; dopara testar antes, como:

for file in *; do echo mv "$file" `echo $file | tr -cd '.A-Za-z0-9_-'` ; done

Outra solução:

rename -v 's/[^a-zA-Z0-9\.\s_-]//g' *.* && rename -v 's/[\s]/_/g' *.*
Námásté Egész-ség.mkv --> Nmst_Egsz-sg.mkv

-n opção para testar antes.


0

Estou procurando uma solução para esse problema há algum tempo. Eu trabalho em sistemas fechados antigos que não podem ter novos pacotes instalados. Eu não tenho o renamecomando. Finalmente, escrevi um script que parece funcionar com todos os caracteres especiais inseridos no teclado. ~@#$%^&*()-_=+[]{}\|;:",<.>?' O script renomeará todos os arquivos e diretórios no diretório atual. Ele substituirá todos os caracteres especiais, exceto -_.pelo _caractere. A outfile=linha pode ser modificada para usar um caractere diferente para substituição, se desejado. Substitua |_|por |.|para usar o .caractere, por exemplo.

#!/bin/bash

for file in ./*
do
  infile=`echo "${file:2}"|sed  \
         -e 's|"\"|"\\"|g' \
         -e 's| |\ |g' -e 's|!|\!|g' \
         -e 's|@|\@|g' -e 's|*|\*|g' \
         -e 's|&|\&|g' -e 's|]|\]|g' \
         -e 's|}|\}|g' -e 's|"|\"|g' \
         -e 's|,|\,|g' -e 's|?|\?|g' \
         -e 's|=|\=|g'  `
  outfile=`echo "${file:2}"|sed -e 's|[^A-Za-z0-9._-]|_|g'`
  mv "$infile" ${outfile} &
done

exit

0

Para mim, no Ubuntu 18.04 LTS com o bash 4.4.20 (1), libere este one-liner funcionou bem para remover espaços, @,: # ...

Para testar (observe o echocomando:

for file in ./* ; do if [[ $file == *['!'\ :@#]* ]]; then echo mv "$file" "${file//[ #()@$:]/_}"; fi; done

Executar:

for file in ./* ; do if [[ $file == *['!'\ :@#]* ]]; then echo mv "$file" "${file//[ #()@$:]/_}"; fi; done
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.