Script ou programa Linux para encurtar nomes de arquivos

8

Não tive muito sucesso em encontrar uma versão Linux do namemangler , que preciso renomear 1000 arquivos para que sejam legíveis no Windows.

Alguém sabe de um programa Linux que pode fazer isso?

Caso contrário, um script poderá funcionar, pois só preciso renomear todos os arquivos em uma pasta para, digamos, os 16 primeiros caracteres. Eu suspeito que a rota do script pode valer a pena ir para baixo, mas não sei por onde começar.

Grimlockz
fonte
2
Você provavelmente poderia escrever rapidamente um script Python ou Perl ou Ocaml ou Ruby fazendo isso.
Por que você não pode simplesmente usar um sistema de arquivos vfat, que permite nomes longos de arquivos?
Wnoise
2
Por curiosidade, por quanto tempo os nomes e o que eles contêm que não são reconhecidos pelo Windows?
Bobby

Respostas:

10

No Debian, Ubuntu e derivados, se você digitar man renameem um prompt de comando, obterá a página de manual para um utilitário de renomeação que permite que comandos arbitrários de expressão regular do tipo Perl sejam usados ​​na renomeação.

Por exemplo, isso reduzirá (truncando) todos os arquivos no diretório atual para um comprimento de cinco:

rename 's/^(.{5}).*/$1/' *

Ele funciona capturando os cinco primeiros caracteres e usando-o na substituição, removendo o restante.

Outro exemplo é reduzir os nomes de arquivos (sans extension) para cinco caracteres, preservando a extensão:

rename 's/^(.{5}).*(\..*)$/$1$2/' *

Ele captura dois grupos, o primeiro sendo o primeiro caractere cinco, o segundo sendo a extensão. Isso iria transformar myCarefullyCraftedDocument.pdfem myCar.pdf.

Aviso: use isso com cuidado, de preferência em uma cópia do seu diretório ou fazendo backups primeiro. Você foi avisado!! No mínimo, use rename -nprimeiro, o que mostrará o que seria feito sem realmente fazê-lo.


fonte
1
isso vai se livrar do prefixo como em PDF? e o que aconteceria com arquivos com o mesmo nome uma vez encurtados?
Esse exemplo em particular, sim. Você pode escrever um regex para deixar a extensão em paz. Vou atualizar a resposta. Ele também protege contra a substituição de arquivos que já existem, portanto, renomeações posteriores falharão.
obrigado por sua ajuda nisso - estou muito agradecido. Eu tenho um pequeno problema se alguns dos PDFs forem renomeados para 5, digamos o que aconteceria com os PDFs que ele tenta renomear com o mesmo nome? Eles são uma maneira de simplesmente adicionar um número único a todos com isso? veja abaixo ename -n 's / ^ (. {5}). * (\ .. *) $ / $ 1 $ 2 /' * Anexos 123114345234525.pdf renomeado como Anexo.pdf Anexos 123114432452352.pdf renomeado como Anexo.pdf
@Grimlockz, não acho que você possa colocar esse tipo de inteligência no próprio nome de regex. O que você pode precisar de fazer é escrever um script para renomear envoltório com esse tipo de inteligência, e que é melhor perguntou como uma questão separada para você conseguir mais pessoas respondendo que apenas I.
@ Grimlockz É por isso que você não quer fazer tudo em uma regex. Você ficará mais feliz e melhor escrevendo um script que use expressões regulares.
Spencer Rathbun
3

Você pode mover arquivos em conflito para outro diretório:

for i in *
do
    j=${i:0:16}

    if [ -e "$j" ]
    then
        mv "$i" /path/to/rename/later
    else
        mv "$i" "$j"
    fi
done
kev
fonte
1

Você pode escrever um script para reduzir nomes de arquivos e remover caracteres que o Windows não gosta em algumas linhas do bash. Aviso, código não testado, digitado diretamente no meu navegador.

shopt -s dotglob extglob
for x in *; do
  y=${x//+([!-!#$%&'().0-9@A-Z^_`a-z{}~])/_}  # change all problematic characters to _
  if [[ $y = .* ]]; then y=_${y#.}; fi        # change dot files to begin with _
  y=${y:0:16}                                 # truncate names
  y=${y,,}                                    # convert to lowercase
  if [[ -e $y || $y =~ ^(aux|clock\$|com[0-9]|con|lpt[0-9]|nul|prn)(\.*)?$ ]]; then
    # The file exists or is a DOS/Windows reserved name.
    # Change foo.bar to foo~1.bar, foo~2.bar, ... (I ignore the length restriction here)
    i=1
    if [[ $y =~ \. ]]; then
      prefix=${y%%.*}; suffix=.${y#*.}
    else
      prefix=$y; suffix=
    fi
    y=${prefix}~$i$suffix
    while [[ -e $y ]]; do
      ((++i))
      y=${prefix}~$i$suffix
    done
  fi
  mv -- "$x" "$y"
done

Se você precisar recursar em subdiretórios, chame um shell script de find -depth -exec …. Ou use zsh em vez de bash; no zsh, **/*(od)expande para todos os arquivos no diretório atual, recursivamente, primeiro com os arquivos mais profundamente aninhados.

Gilles 'SO- parar de ser mau'
fonte
1

Os scripts shell / python / perl para esse tipo de coisa são bons, mas parece que um aplicativo de interface gráfica seria o melhor para você, então eu recomendaria o pyRenamer , que pode fazer exatamente o que você deseja, entre muitas outras coisas (operações comuns simples através de predefinições [se livrando de espaços, truncando o nome do arquivo de um ponto para outro], pesquisa / substituição simples, regex complicado, visualizador, etc).

Sua distribuição pode até tê-la em seu repositório de software (o Fedora possui).

rsaw
fonte
0

Alguns sistemas não possuem o renamecomando, portanto, como alternativa à resposta do paxdiablo, veja como fazer a mesma coisa mv.

for f in *.pdf; do 
    tmp=`echo $f | sed -r 's//^(.{5}).*(\..*)$/$1$2/'`
    mv -b ./"$f" ./"$tmp"
done

O -bsinalizador em movimento cria um backup dos arquivos que seriam excluídos ou substituídos. Alterando o padrão glob no loop for, você pode ajustar quais arquivos são executados, usando *por si só para executar todos os arquivos.

Spencer Rathbun
fonte
1
Não há necessidade de usar echoe um pipe (pode ser muito caro se você tiver muitos arquivos), use um heredoc ou herestring.
21712 Chris Down
1
@ChrisDown veja aqui . De acordo com o artigo da wiki , os processos canalizados são bifurcados, mas não diz nada sobre executá-los em seus próprios shells.
Spencer Rathbun
1
Por exemplo, observe a diferença entre eval 'echo $BASH_SUBSHELL'e eval 'echo $BASH_SUBSHELL' | cat.
31412 Chris Down
2
Acabei de fazer um teste rápido, timeusando um loop usando echo $i | sede outro usando sed ... <<<$i, e o herestring levou cerca de 2/3 do tempo do eco.
21412 Kevin
1
@SpencerRathbun Sim. <<inicia um <i> doc </i> aqui, que é multi-linhas e requer delimitadores. <<<cria uma <i> string </i> aqui, que leva apenas uma variável / string. Experimente var=abc // cat<<<$var // cat <<$var.
21712 Kevin
0

Se você precisar renomear arquivos e tiver bibliotecas do KDE instaladas no seu sistema (ou não se importa de adicioná-las), confira o krename.

Ele permite executar várias tarefas simples de renomeação diretamente com suas ferramentas e também permite expressões regulares para situações mais complicadas.

Ele mostra uma visualização dos arquivos renomeados conforme você cria as condições de renomeação. Ele também permite que você renomeie os mesmos arquivos novamente, o que é útil se você quiser fazer algo complicado, pois fazê-lo em estágios reduziria a complexidade de cada estágio a algo que você pode descobrir rapidamente.

Joe
fonte
-1
for file in *; do
    mv "$file" $(echo "$file" | sed -e 's/[^A-Za-z0-9._-]/_/g')
done &
Jairo Bernal
fonte