Renomear arquivos e não diretórios

2

Eu quero renomear todos os arquivos para minúsculos em um diretório sem renomear os subdiretórios. Eu sei renomear função mas renomeia arquivos e subdiretórios que não é desejado. Você pode ajudar?

    
por mony 25.10.2015 / 22:15

5 respostas

3

Tudo pode ser feito na expressão perl.

Use -f , o teste regular de arquivos, para que apenas arquivos regulares (não diretórios) sejam renomeados.

Isso funciona:

rename 'y/A-Z/a-z/ if -f;' ./*

(Usar ./* em vez de * garante que nenhum nome de arquivo seja interpretado como opção, mesmo que o nome do arquivo comece com um traço (-).

    
por 25.10.2015 / 23:53
2

com zsh :

autoload zmv # best in ~/.zshrc
zmv '*(#q^/)' '${(L)f}'

Para renomear arquivos de qualquer tipo, exceto o diretório. Ou:

zmv '*(#q.)' '${(L)f}'

Para renomear apenas arquivos regulares. Para incluir também arquivos ocultos, adicione o qualificador D glob.

Exemplo (usando -n para execução a seco):

$ ls -alQF
total 132
drwxr-xr-x   3 stephane stephane   4096 Oct 27 09:11 "."/
drwxr-xr-x 533 stephane stephane 122880 Oct 27 09:11 ".."/
drwxr-xr-x   2 stephane stephane   4096 Oct 27 09:07 "DIR"/
lrwxrwxrwx   1 stephane stephane      3 Oct 27 09:07 "DIR-LINK" -> "DIR"/
prw-r--r--   1 stephane stephane      0 Oct 27 09:07 "FIFO"|
-rw-r--r--   1 stephane stephane      0 Oct 27 09:11 ".HIDDEN FILE"
-rw-r--r--   1 stephane stephane      0 Oct 27 09:07 "HOLIDAYS IN МОСВА\nRED SQUARE.JPG"
lrwxrwxrwx   1 stephane stephane     23 Oct 27 09:08 "MY-RÉSUMÉ.PDF" -> "STÉPHANE'S RÉSUMÉ.PDF"
-rw-r--r--   1 stephane stephane      0 Oct 27 09:07 "--READ-ME--.TXT"
srwxr-xr-x   1 stephane stephane      0 Oct 27 09:09 "SOCKET"=
-rw-r--r--   1 stephane stephane      0 Oct 27 09:07 "STÉPHANE'S RÉSUMÉ.PDF"

$ zmv -n '*(#q^/)' '${(L)f}'
mv -- DIR-LINK dir-link
mv -- FIFO fifo
mv -- HOLIDAYS\ IN\ МОСВА$'\n'RED\ SQUARE.JPG holidays\ in\ мосва$'\n'red\ square.jpg
mv -- MY-RÉSUMÉ.PDF my-résumé.pdf
mv -- --READ-ME--.TXT --read-me--.txt
mv -- SOCKET socket
mv -- STÉPHANE\'S\ RÉSUMÉ.PDF stéphane\'s\ résumé.pdf

$ zmv -n '*(#q.)' '${(L)f}'
mv -- HOLIDAYS\ IN\ МОСВА$'\n'RED\ SQUARE.JPG holidays\ in\ мосва$'\n'red\ square.jpg
mv -- --READ-ME--.TXT --read-me--.txt
mv -- STÉPHANE\'S\ RÉSUMÉ.PDF stéphane\'s\ résumé.pdf

$ zmv -n '*(#qD.)' '${(L)f}'
mv -- .HIDDEN\ FILE .hidden\ file
mv -- HOLIDAYS\ IN\ МОСВА$'\n'RED\ SQUARE.JPG holidays\ in\ мосва$'\n'red\ square.jpg
mv -- --READ-ME--.TXT --read-me--.txt
mv -- STÉPHANE\'S\ RÉSUMÉ.PDF stéphane\'s\ résumé.pdf

Veja como alguns deles quebrariam alguns links simbólicos.

    
por 26.10.2015 / 22:10
1

A conversão para minúsculas pode ser feita digitando-se um var em minúsculas.

EDIT: Solução substituída com find para uma solução com for .

Primeiro tentei uma solução usando find , esperando encontrar arquivos apenas com -type f .
Isso parece funcionar bem:
Eu usei -maxdepth 1 , então eu não mudei nada em outras pastas (o que seria um pouco mais difícil quando um nome de diretório está em maiúsculas). Isso resultou em

typeset -l smallfile
echo "Find solution looks OK but read more..."
find .-maxdepth 1 -type f| while read file; do
        smallfile="${file}"
        mv "${file}" "${smallfile}"
done

Eu pensei que esta construção iria lidar com nomes de arquivos com espaços corretamente, o que eu testei com nomes de arquivos como "File with Spaces". @Chazelas comentou corretamente que a solução falha com nomes de arquivos que terminam com um espaço ("Muito ruim"). Outro comentário explica como corrigir o find -command: find ... -print0 | while IFS= read -rd '' file (seu find deve suportar print0 , principalmente bash e zsh ).
Como eu já estou usando um loop, também posso usar test para ver que o item atual (fornecido por * ) é um arquivo regular.
Eu encontrei uma solução com um loop simples e mostrei aqui, incluindo meu código de teste.

#!/bin/bash
clear
rm -rf testfiles 2>/dev/null
mkdir -p testfiles/SomeDir #2>/dev/null
mkdir testfiles/"Crazy Dir" 2>/dev/null
touch testfiles/Aha testfiles/"File with Spaces" testfiles/"End with space "
ls -lQ testfiles
echo ===================
typeset -l smallfile
for file in testfiles/* # Stack's formatting thinks /* starts comment, so I close that here: */
do
   if [ -f "${file}" ]; then
        smallfile="${file}"
        # echo mv "${file}" "${smallfile}"
        mv "${file}" "${smallfile}"
   fi
done
echo ===================
ls -lQ  testfiles

Para o diretório atual, remova testdir/ do loop for.

    
por 25.10.2015 / 22:55
1

Você pode tentar

cd directory ; rename 'y/A-Z/a-z/' $(ls -p | grep -v /$) ; cd -

Mas é melhor usar find

cd directory ; find * -prune -type f -exec rename 'y/A-Z/a-z/' {} + ; cd -
    
por 25.10.2015 / 22:53
0

Este oneliner resolverá:

find path-to-search -depth -type f -exec rename 's/(.*)\/([^\/]*)/$1\/\L$2/' {} \;

Cya!

    
por 27.10.2015 / 20:27