Como eu faço uma substituição para '$ 0' mas salvo o valor antigo?

1

Estou tentando renomear todos os arquivos que começam com um "m" para ser o mesmo nome, exceto que o primeiro caractere (ou "m", neste caso) foi removido.

Minha estratégia é:

  1. Listar todos os arquivos com ls
  2. Filtre por aqueles que eu quero, com egrep
  3. Gere a string que eu não quero ao lado da que eu quero, separada por um espaço, com awk , por exemplo, mfoo foo
  4. Feed em xargs to mv mfoo foo

Algumas perguntas:

  • Esta é uma boa estratégia?
  • Qual é o melhor?

Estou preso no Passo 3, abaixo é como eu abordei o problema.

Estou trabalhando no seguinte diretório:

$ find .
.
./cat
./mbar
./mbaz
./mfoo

Eu consigo rapidamente 1-2:

$ ls | egrep '^m'
mbar
mbaz
mfoo

O passo 3 é mais difícil. Eu usei gsub para gerar a segunda sequência de caracteres desejada, mas não sei como "colá-la junto com o valor original separado por um espaço":

$ ls | egrep '^m' | awk '{ gsub(/^./, ""); print }'
bar
baz
foo

O passo 4 faz sentido para mim, embora eu não tenha certeza de como terminar o Passo 3, então não posso terminar ainda. Abaixo está um exemplo de como eu acho que deve funcionar:

$ echo mfoo foo | xargs mv
$ find .
.
./cat
./foo
./mbar
./mbaz

Acho que estou perto, só preciso descobrir como salvar o valor antigo e imprimi-lo ao lado do valor gsubed. Eu tentei o seguinte pequeno exemplo, mas não está funcionando:

$ echo mfoo | awk '
pipe quote> { old = $0 }
pipe quote> { new = gsub(/^./, "") }
pipe quote> { print $old " " $new }'
awk: illegal field $(mfoo), name "old"
 input record number 1, file
 source line number 4
  • Como faço uma substituição para $0 , mas salve o valor antigo?
  • Por que estou recebendo esse erro?
por mbigras 09.04.2017 / 23:18

3 respostas

2
ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -l -t mv

A implementação do Posix- ly é feita através da opção -L para xargs as:

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); $0 = x " " $0 }1' | xargs -L 1 -t mv

ls | egrep '^m' | awk '{ x=$0; gsub(/^./, ""); print x, $0 }' | xargs -L 1 -t mv

Com base no que eu respondi à sua consulta anterior sobre xargs , podemos colocar esse aprendizado em boa qualidade use neste exemplo.

Eu modifiquei um pouco o seu código awk : ele preserva a linha original ( $0 ) já que a função gsub vai derrotá-lo. Em seguida, reunimos o antigo & o novo para obter a linha que queremos enviar para xargs , que então invocará mv com os argumentos certos para efetuar a renomeação.

    
por 10.04.2017 / 01:59
7

Isso deve lidar com toda a operação:

for file in m*; do mv "${file}" "${file#m}"; done

Antes de executar, verifique primeiro as coisas com

for file in m*; do echo mv "${file}" "${file#m}"; done

Isso usa m* glob para as etapas 1 e 2, depois ${file#m} (que remove “m” do início de ${file} ) para a etapa 3 e, finalmente, um loop para a etapa 4.

Para responder à sua pergunta sobre o AWK, você pode fazer desta maneira:

echo mfoo | awk '{ print $0, substr($0, 2) }'

As variáveis do AWK não usam $ , apenas para campos; é de onde vem o erro: o AWK entende $old como "o valor do campo numerado de acordo com o valor de old ". É mais fácil ler também se você colocar seus comandos em um único bloco (supondo que eles tenham o mesmo padrão). Corrigindo seu script dá

echo mfoo | awk '{ old = $0; gsub(/^./, ""); print old, $0 }'
    
por 09.04.2017 / 23:21
2

Uma estratégia melhor é usar o comando rename .

Observe que a sintaxe exata desses comandos é específica da distribuição, consulte a página man da sua versão específica da distribuição. No Ubuntu, por exemplo, que tem uma implementação Perl de rename , você pode usar um regex:

rename -nono 's/^m//' m*

Observação: remova o sinalizador -nono para realmente executar a renomeação.

    
por 10.04.2017 / 05:08