Eu quero minúsculas o nome de todos os diretórios em um diretório. Com quais comandos posso fazer isso?
fonte
Eu quero minúsculas o nome de todos os diretórios em um diretório. Com quais comandos posso fazer isso?
Todos os diretórios em um nível ou recursivamente?
Em um nível:
autoload zmv
zmv -o-i -Q 'root/(*)(/)' 'root/${1:l}'
Recursivamente:
zmv -o-i -Q 'root/(**/)(*)(/)' 'root/$1${2:l}'
Explicações: zmv
renomeia os arquivos que correspondem a um padrão de acordo com o texto de substituição fornecido. -o-i
passa a -i
opção para cada mv
comando 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 $2
para minúsculas.
Em um nível:
for x in root/*/; do mv -i "$x" "$(printf %s "$x" | tr '[:upper:]' '[:lower:]')"; done
O final /
restringe a correspondência aos diretórios e mv -i
solicita a confirmação em caso de colisão. Remova o -i
para substituir em caso de colisão e use yes n | for …
. para não ser solicitado e não executar nenhuma renomeação que colidiria.
Recursivamente:
find root/* -depth -type d -exec sh -c '
t=${0%/*}/$(printf %s "${0##*/}" | tr "[:upper:]" "[:lower:]");
[ "$t" = "$0" ] || mv -i "$0" "$t"
' {} \;
O uso de -depth
garante que os diretórios profundamente aninhados sejam processados antes de seus ancestrais. O processamento de nomes depende da existência de um /
; se você quiser chamar de operar no diretório atual, use ./*
(adaptar o shell script para lidar com .
ou *
é deixado como um exercício para o leitor).
Aqui eu uso o script de renomeação do Perl que o Debian e o Ubuntu lançam como /usr/bin/prename
(normalmente também disponíveis rename
). Em um nível:
rename 's!/([^/]*/?)$!\L/$1!' root/*/
Recursivamente, com bash ≥4 ou zsh:
shopt -s globstar # only in bash
rename 's!/([^/]*/?)$!\L/$1!' root/**/*/
Recursivamente, portably:
find root -depth -type d -exec rename -n 's!/([^/]*/?)$!\L/$1!' {} +
mv -i a a
dê "mv: renomeie a para a / a: argumento inválido".-execdir
que é incrível: unix.stackexchange.com/questions/5412/… Descobri que ele tinha umaPATH
loucura e ficou triste :-(Não há um único comando que faça isso, mas você pode fazer algo assim:
Se você precisar que ele seja robusto, considere quando já existem dois diretórios que diferem apenas no caso.
Como uma linha:
fonte
for file in * ; do if [ -d "$file" ] ; then dest="$(echo $file | sed y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/)" ; [ "$dest" != "$file" ] && mv "$file" "$dest" ; fi ; done
find -type d
, mas não consegui entenderfor fd in */;
, evitando assim a necessidade de verificar se era um diretório, mas não tenho idéia se esse instinto era bom.tr
já espera um intervalo, entãotr '[A-Z]' '[a-z]'
traduz[
para[
e]
para]
de passagem. Isso é inútil, mas inofensivo; no entanto, sem as aspas, o shell expandiria os colchetes se houvesse um arquivo com o nome de uma letra maiúscula no diretório atual.Tomei isso como um desafio de uma linha :) Primeiro, estabeleça um caso de teste:
Eu uso
find
para localizar os diretórios com letras maiúsculas e depois colocá-los em minúsculas . Acho que usar é um pouco hack-ish, mas minha cabeça sempre explode quando tento escapar das coisas diretamente.sh -c 'mv {}
echo {} | tr [:upper:] [:lower:]
'sh -c
find
Esteja avisado: Esta solução não verifica se o downcasing causa colisões!
fonte
mv -i
. Um problema maior é que você não usou a citação adequada; portanto, seu comando falhará se houver caracteres especiais (espaço em branco ou\[*?
) em qualquer lugar do nome. Não há nenhum ponto de usar, afind
menos que seja recorrente, e então você precisafind -depth
e-path
deve ser-name
. Veja minha resposta para exemplos de trabalho.mv -i
depois de escrever isso. Bom ponto com a citação ...find -execdir
| renomearEssa seria a melhor maneira de fazer isso, se não fosse a loucura relativa do caminho, pois evita que o Regex fu do Perl atue apenas no nome da base:
-execdir
primeirocd
s no diretório antes de executar apenas no nome da base.Infelizmente, não consigo me livrar dessa
PATH
parte de hackers,find -execdir
se recusa a fazer qualquer coisa se você tiver um caminho relativo emPATH
...: /ubuntu/621132/why-using-the-execdir-action- é inseguro para o diretório que está no caminho / 1109378 # 1109378fonte