Existe um comando linux como mv, mas com regex?

41

Por exemplo, eu quero mv (.*?).sql $1.php,

existe um comando que me permita especificar padrões de renomeação?

JoshRibs
fonte

Respostas:

32

Como outros já mencionaram, renameé bom nisso, mas leia a página de manual ( man rename) antes de tentar. Existem pelo menos duas ferramentas completamente diferentes por aí chamadas renamee qual delas você dependerá da sua distribuição. Chamá-los incorretamente pode ser perigoso.

Aqui está a página de manual da versão baseada em perl de Larry Wall que acompanha o Ubuntu. Você dá uma expressão perl comorename 's/\.sql$/.php/' *.sql

Aqui está a página do manual para renomear as distribuições Red Hat e CentOS mais antigas. O uso é simples substituição de string comorename .sql .php *.sql

Você também pode usar uma linha de base do bash para processar cada arquivo, um de cada vez:

$ for f in *.sql; do mv -i "$f" "${f%%.*}.php"; done
Ryan Bright
fonte
Alguém poderia fazer upload de um binário do Windows para a renomeação baseada em perl?
mcandre
A renomeação da versão Perl não pode mover arquivos de um sistema de arquivos para outro.
Lilydjwg
festa um forro é útil, especialmente quando se tem nenhuma renamefunção (isto é, busybox)
artm
10

rename(1), que não usa expressões regulares, mas pode resolver seu problema:

rename .sql .php *.sql

Há também mmv(1), mas não estou familiarizado com o funcionamento.

Adam Rosenfield
fonte
No Ubuntu e Debian (não tenho certeza sobre outras distribuições), os /usr/bin/renamelinks são /usr/bin/prenamepor padrão, o que leva regexps.
28909
5

G'day,

Você também pode tentar entrar

for i in $(\ls -d *.sql)
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

Ou, para fazê-lo usar a expressão regular, altere-a ligeiramente para

for i in $(\ls -d | egrep -e '.*\.sql')
do
mv $i $(echo $i | sed -e 's/\.sql$/\.php/')
done

para se divertir um pouco com a codificação de shell. (-:

Rob Wells
fonte
2
Isso falha com arquivos que contêm espaços em branco em seus nomes, portanto, tenha cuidado. Nunca sels deve analisar a saída .
slhck
O sedexemplo é bastante bom, no entanto.
bright-star
2

Sendo um encanador, eu gosto de canos :)

Nota: esta resposta é detalhada - como uma novata, agradeço quando alguém que sabe dedica algum tempo para explicar, por isso estou pagando 'adiante'. Se você não é um novato, desculpe o comprimento e a verbosidade.

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/' | bash

Onde:

ls -1 *_201[67][0-9]*

lista todos os arquivos que correspondem ao padrão; nesse caso, estou procurando arquivos com a data no nome do arquivo no formato 'AAAAMMDD'

sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'
#        : | |    |     |                  | |       |                    |:                                 :
#        : |^2....^    ^3..................^^4.......^                    |:                                 :
#        :^1..............................................................^:                                 :
#        /................filename.................pattern................./...mkdir...and....mv...command.../

^ 1: 1º grupo de captura - o nome do arquivo inteiro

^ 2: 2º grupo de captura - a 1ª parte do padrão de nome de arquivo

^ 3: 3º grupo de captura - a 2ª parte do nome do arquivo - aqui, a data como 'AAAAMMDD'

^ 4: 4º grupo de captura - parte opcional do nome do arquivo entre a data e a extensão e a própria extensão

Tããããão .... se eu tiver um arquivo chamado

CallLog_555123412_20161231-214403.7z

...então

mkdir -p \2\/\3; mv \1 \2\/\3\/\1

na verdade significa

# make directory and sub-directory
mkdir -p CallLog_555123412/20161231
# move file from current directory to sub-sub-directory just created
mv CallLog_555123412_20161231-214403.7z CallLog_555123412/20161231/CallLog_555123412_20161231-214403.7z

Observe que a saída do comando sed é canalizada para 'bash' para executá-lo. Para ver primeiro o arquivo proposto se move SEM realmente movê-los, remova primeiro o '| bash 'no final e tente assim:

ls -1 *_201[67][0-9]* | sed -e 's/\(\(.\+\)[-_]\(201[67][0-9]\{4\}\)\([^.]\+\)\?\.[0-9a-z]\{2,3\}\)/mkdir -p \2\/\3; mv \1 \2\/\3\/\1/'

Isso não fará nenhuma alteração, mas você verá o comando que será executado SE você executá-lo com '| bash 'marcado com a etiqueta no final.

Isso é útil porque você pode criar qualquer subdiretório desejado a partir de partes no nome do arquivo ou qualquer outra coisa que você adicionar ao texto 'substituto' no comando sed. Note que o sed requer muitos caracteres de escape.

Suportes Regex SED:

(...) exigem escape para agrupamento de capturas -> \ (... \)

{m, n} exige escape para quantificar o objeto anterior -> \ {m, n \}

/ requer escape na cadeia de substituição -> \ /

[...] NÃO requer escape para classes de personagens

\ 1 na cadeia de substituição refere-se ao primeiro grupo capturado e assim por diante ...

AVISO DE SEGURANÇA: NUNCA TUBE QUALQUER COISA PARA 'FAZER', A menos que você entenda totalmente o resultado ...

Espero que ajude a eliminar alguns bloqueios :)

skeetastax
fonte
1

Instale mmve faça o seguinte:

mmv "*.sql" "#1.php"
Gepsens
fonte