alterar toda a árvore de diretórios para nomes em minúsculas

12

Estou trabalhando na conversão de um site. Os arquivos que foram vinculados e servidos no servidor da Web não diferenciam maiúsculas de minúsculas. Mas fiz um despejo do site no meu sistema Linux e estou escrevendo scripts para migrar dados. O problema é que estou enfrentando problemas de distinção entre maiúsculas e minúsculas entre as seqüências de links nas páginas e as palavras reais no sistema de arquivos.

Por exemplo, uma página pode ter um link como <a href='/subfolder/PageName.asp'>o arquivo real /subfolder/pagename.asp. Da mesma forma com imagens - <img src='spacer_sm.gif'>pode ser Spacer_Sm.gif.

Então, meu pensamento é alterar todos os nomes de diretório e arquivos para seus equivalentes em minúsculas para o download do site. Como faço isso (e pode haver uma maneira melhor?)

Mesmo se houver comandos unix com opções que não fazem distinção entre maiúsculas e minúsculas, estou usando php, portanto nem todos os comandos do sistema de arquivos têm opções para diferenciação entre maiúsculas e minúsculas.

user394
fonte
2
Veja uma pergunta anterior semelhante . Repostei aqui uma resposta mais simples, porque a pergunta é um pouco mais específica.
Gilles 'SO- stop be evil'

Respostas:

8

Não sei se o seu sabor unix tem um rename. Muitos Linux têm, e fazem parte de um pacote perl, se você procurar um repositório.

find ./ -depth -exec rename -n 'y/[A-Z]/[a-z]/' {} ";"

Versão acima com

rename -n 

realmente não executa a ação, mas apenas imprime o que seria feito. Você omite o -n para fazer isso de verdade.

Usuário desconhecido
fonte
Qual 'idioma' ou regex é a 'y/[A-Z]/[a-z]/'parte?
user394
Bem, como renamefaz parte de um perlpacote, acho que o perl, mas o padrão também é usado sed, e talvez AWKtambém. Eu só sei sedbem quieto. Traduzo ypara translateou map, mas não sei de onde o personagem se origina.
usuário desconhecido
Deve ser perl regex - Gilles, em sua resposta, diz que renameé um script perl.
user394
Sim, e você pode usar regexs perl para modificar os nomes de arquivos, o que não significa necessariamente que seja escrito em perl, mas que pode ser a pergunta mais interessante.
usuário desconhecido
9

Zsh

zmv -o-i '(**/)(*)' '$1${2:l}'

Explicações: zmvrenomeia os arquivos que correspondem a um padrão de acordo com o texto de substituição fornecido. -o-ipassa a -iopção para cada mvcomando sob o capô (veja abaixo). No texto de substituição, $1, $2, etc, são os grupos entre parênteses sucessivas no padrão. **significa todos os (sub) * diretórios, recursivamente. A final (/)não é um grupo entre parênteses, mas um qualificador global que significa corresponder apenas aos diretórios. ${2:l}converte $2para minúsculas.

Renomear Perl

Aqui eu uso o script de renomeação do Perl que o Debian e o Ubuntu /usr/bin/prenamedisponibilizam (normalmente também disponíveis rename). Com bash ≥4 ou zsh:

shopt -s globstar  # only in bash
rename 's!/([^/]*/?)$!\L/$1!' **/*

Com outras conchas:

find . -depth -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +

Portátil

Recursivamente:

find . -depth -exec sh -c '
    t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
    [ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;

O uso de -depthgarante que os diretórios profundamente aninhados sejam processados ​​antes de seus ancestrais.

Gilles 'SO- parar de ser mau'
fonte
1

Não funcionou na seguinte estrutura de diretórios:

JKL/
deF/
ABC/DEf
ABC/gHi
ghi/jkL

Aqui está um exemplo que funciona:

for i in `find | sort -r | sed '$d'`; do \
   b=${i%/*}; e=${i##*/}; mv $i $b'/'${e,,}; done

Para uma explicação sobre be evars:

man bash

Em seguida, use a seguinte sequência de teclas: /,,Enterbb

Baronsed
fonte
0

A resposta aceita não funcionou para mim, pois tentou alterar todos os diretórios de uma só vez. Encontrei outra solução no stackexchange muito semelhante à portátil do Gilles acima: da Baramin -
/programming/4268591/unix-rename-files-directories-to-uppercase

Eu copiei aqui:

find . -depth | \
while read LONG; do
   SHORT=$( basename "$LONG" | tr '[:lower:]' '[:upper:]' )
   DIR=$( dirname "$LONG" )
   if [ "${LONG}" != "${DIR}/${SHORT}"  ]; then
     mv "${LONG}" "${DIR}/${SHORT}"
   fi
done

Para o qual eu mudei o comando tr para ie: sed s / cat / dog / g

Agradeço a Baramin no link acima.

JJones
fonte