Qual é um bom comando para excluir espaços, hífens e sublinhados de todos os arquivos em um diretório ou arquivos selecionados?
Eu uso o seguinte comando com Thunar Custom Actions para slugify nomes de arquivos:
for file in %N; do mv "$file" "$(echo "$file" | tr -s ' ' | tr ' A-Z' '-a-z' | tr -s '-' | tr -c '[:alnum:][:cntrl:].' '-')"; done
Mas esse comando substitui apenas espaços por traços / hífens e caracteres com letras minúsculas.
Eu usei o seguinte comando no terminal para excluir espaços de milhares de nomes de arquivos em uma pasta e funcionou muito rápido:
rename "s/ //g" *
Novamente, ele exclui apenas espaços, e não hífens / traços e sublinhados também.
Idealmente, não quero espaços, hífens / traços e sublinhados nos meus nomes de arquivos. E seria ótimo se o comando pudesse ser usado com ações personalizadas da Thunar nos arquivos selecionados.
shell-script
files
rename
user8547
fonte
fonte
rename -i "s/[-_ ]//g" *
echo $file | sed -e 's/[ _-]//g'
; doneRespostas:
A versão
rename
disso vem com operl
pacote suporta expressões regulares:Alternativamente,
O
-i
sinalizador farárename
uso do modo interativo, perguntando se o destino já existe, em vez de substituir silenciosamente.O nome do Perl é chamado às vezes
prename
.Renomeação de Perl versus renomeação de util-linux
Em sistemas parecidos com o Debian, a renomeação do perl parece ser o padrão e os comandos acima devem funcionar.
Em algumas distribuições, o
rename
utilitário do util-linux é o padrão. Este utilitário é completamente incompatível com o Perlrename
.Todos: Primeiro, verifique se o Perl
rename
está disponível sob o nomeprename
.Debian: A renomeação do Perl deve ser o padrão. Também está disponível como
prename
. Orename
executável, porém, está sob o controle/etc/alternatives
e, portanto, poderia ter sido alterado para algo diferente.archlinux: Execute
pacman -S perl-rename
e o comando está disponível comoperl-rename
. Para um nome mais conveniente, crie um alias. (Dica do chapéu: ChiseledAbs)Mac OSX De acordo com esta resposta ,
rename
pode ser instalado no OSX usando homebrew via:Download direto:
rename
também está disponível em Perl Monks:fonte
rename
você está falando. O do util-linux -2.24.2-1.fc20.x86_64 não suporta expressões regulares.rename
que o OP estava usando se parece com aperl
versão e não com autil-linux
versão.rename
página de manual da versão util-linux . De qualquer forma, além dessa nota, o importante é que o OP tenha a resposta dele (e você fez um voto positivo :-D).pacman -S perl-rename
então eu acho que você pode alias.Eu substituiria todos esses
tr
comandos, por umsed
comando de substituição, por exemplo:fonte
Sem contar
mv
, você realmente não precisa de um processo de fora para este em tudo - você pode tipo de apenas poof -los.Ainda assim, isso significa uma
mv
chamada por arquivo e, provavelmente,rename
é melhor. Embora isso deve funcionar dado apenas um POSIXmv
em$PATH
e um shell POSIX.Então, eu vim com uma espécie de demonstração louca por isso. O conjunto de testes é gerado como:
Em primeiro lugar, serei o primeiro a reconhecer que o comando acima produz resultados que podem ser obtidos mais facilmente por outros meios. Mas outros meios provavelmente não demonstrariam tão bem o que poderia ser feito
$IFS
e um pouco de imaginação (doentia) .Portanto, o primeiro bit é bastante direto:
tee
canaliza 5 cópias de sua entrada - o documento hereditárioCGEN
dd
bloqueia sua entrada por novas linhas a 90 bytes por bloco e canaliza para ...sed
une 2 desses blocos em dois\n
caracteres ewline,'
aspas simples os resultados e precede a sequênciatouch --
de caracteres para cada ciclo de linha antes de ...sh
que executa todas as entradas como comandos do shellO
#CGEN
pouco embora ... Bem, brevemente ...a parte inferior
printf
imprime 252 0so próximo da última recebe 252
''
argumentos de cadeia nula e, para cada um, imprime o conteúdo de$n
seguido pela cadeia" $i "
eval
interpreta os argumentos do próximoprintf
item antes de imprimir os resultados dessa interpretação como números octais, precedidos por 2 barras invertidas por peçao último
printf
imprime os valores de bytes para os octais 2 de cada vez, seguidos pela sequência-_ ---___
de caracteres para cada par$n
é inicializado com uma equação que será incrementada$i
em um para cada avaliação, exceto pelo fato de ignorar os valores 10, 39 ou 47 - (que são linha de\n
ew, aspas'
simples e/
barra em decimal ASCII, respectivamente)O resultado final é um diretório que contém muitos nomes de arquivos realmente feios, contendo todos os bytes no meu conjunto de caracteres de 1 a 255, exceto as aspas simples (puladas para evitar mais uma
sed s///
declaração) e a/
barra. Esses nomes de arquivos são assim:Agora vou obter alguns dados sobre esses arquivos:
RESULTADO
Está bem. Agora, finalmente, para a ação:
RESULTADO
Sucesso! Você pode ver por si mesmo:
fonte
IFS
+printf
set -- 'some arbitrary' args; eval printf '"%s\n"' "$(IFS=0; printf ' "$@" %s' $(printf %025d))"
new="$(IFS=" -_"; printf %s $1)"
bifurca um subshell (exceto no ksh93) e tem problemas com as novas linhas de cauda. Outra opção é o usoIFS=' -_'; set -- $1; IFS=; new="$*"
(e mudar seu loop while para um loop)[ -e x ]
retornará false sex
for um link simbólico para um arquivo inexistente ou não acessível.se você tem perl, geralmente renomeia. você pode fazer:
e mostre como esse script está escrito:
Este script não suporta a sinalização -i (esta é a versão no meu sistema), mas talvez o seu suporte. E os argumentos. Primeiro é expressões regulares com o formato PCRE, funciona como filtro, modifica o nome da entrada para o nome da saída. Lista de nomes de entrada fornecidos pelo asterisco '*'. por exemplo, você faz:
em real '*' pode ser expandido para:
Quando você tem arquivos de contagem realmente grandes, está preso. O shell expandirá sua linha por mais tempo do que o sistema aceita. então você pode executar uma solução alternativa usando find ou xargs. usar 'find' é um problema, porque renomear será chamado muitas vezes igual à contagem de arquivos no diretório melhor usar xargs com a opção -r. uma chamada de renomeação modifica muitos arquivos. por exemplo:
último problema, o que significa:
esta é uma expressão regular para modificar nomes. depois do primeiro '/' é o espaço. isso é detectado e substituído por uma sequência após o segundo '/'. Mas há uma string vazia terminada com o terceiro '/', depois o espaço é substituído por nada. A opção 'g' torna essa expressão repetitiva. A expressão percorrerá todo o nome do começo ao fim e detectará todos os espaços.
Mas e se você tiver um caractere de tabulação ou outro caractere 'branco'? há substituto para esse '\ s'. que outros personagens desnecessários? basta adicioná-lo à expressão. Todos fecham com colchetes, por exemplo:
Isso é tudo. você vê similaridade? Acho que você deveria ler man perlrequick e man perlretut, isso explica (espero) como a expressão regular funciona. você pode usar o comando rename em seu próprio script, se precisar.
fonte
O seguinte
sh
loop de shell removerá todos os espaços, sublinhados e hífens dos nomes dos arquivos no diretório atual, tomando o cuidado de não sobrescrever nenhum arquivo existente:Para
bash
eksh
sendo um pouco mais detalhado com a lógica:Remova o
echo
quando tiver certeza de que faz o que deseja.O
tr
comando excluirá (-d
) qualquer caractere no conjunto de caracteres especificado (' _-'
). É importante ter o traço no início ou no final do conjunto, ou será interpretado como um intervalo de caracteres.fonte