Renomeie o arquivo usando grep e for

Renomeie o arquivo usando grep e for

Gostaria de renomear arquivos com as seguintes extensões: .txt, .data, .conf para ".xml"

olá.txt -> olá.xml

Para isso, o arquivo também deve conter a seguinte linha:<?xml version="1.0" encoding="UTF-8"?>

Isto é o que eu tenho:

for file in *
do
if [ $(grep -Rc '<?xml version="1.0" encoding="UTF-8"?>' --include ".txt" --include ".data" --include "*.conf") = true ]
then
rename extension to: .xml
fi
done

Alguma ideia?

Responder1

Se vocêprecisarfazer isso grepe forentão talvez algo assim?

grep -RlZ '<?xml version="1.0" encoding="UTF-8"?>' --include "*.txt" --include "*.data" --include "*.conf" | 
  xargs -0 sh -c 'for f; do echo mv -- "$f" "${f%.*}.xml"; done' sh

(remova echoquando estiver convencido de que está fazendo a coisa certa).

  • grep -RlZgera uma lista delimitada por nulos dos nomes dos arquivos onde as correspondências são encontradas

  • xargs -0passa essa lista separada por nulos parash -c

  • for fpercorre os nomes dos arquivos como parâmetros posicionais

ou (se você tiver permissão para usar whileem vez de for), você pode pular xargso scriptlet adicional do shell, como

grep -RlZ '<?xml version="1.0" encoding="UTF-8"?>' --include "*.txt" --include "*.data" --include "*.conf" | 
  while IFS= read -r -d '' f; do echo mv -- "$f" "${f%.*}.xml"; done

Responder2

find . -type f \( -name "*.txt" -o -name "*.data" -o -name "*.conf" \) -exec sh -c '
    for file in "$@"; do
        if grep -qF "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "$file"; then
            mv -- "$file" "${file%.*}.xml"
        fi
    done
' findshell {} +

Acho que findé mais adequado neste contexto. Ele procura recursivamente arquivos regulares com .txtextensões .datae .confverifica se a string que você forneceu está presente em cada um deles. Se sim, então a extensão será alterada .xmlpor um mvcomando.

Se não tiver certeza se o código funcionará conforme o esperado, você pode adicionar um echobefore mvpara ver o que ele faz.

Devo também mencionar que esse script não depende de utilitários não POSIX.

Responder3

Você pode tentar isso:

for file in *.{txt,conf}; do 
  [[ $(grep "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "$file") ]] && \
  mv "$file" "${file%.*}.xml" || echo "$file" " does not match"
done

Responder4

Usando bash:

shopt -s globstar dotglob nullglob extglob

string='<?xml version="1.0" encoding="UTF-8"?>'

for pathname in ./**/*.@(txt|data|conf); do
    if [[ -f $pathname ]] && grep -q -F "$string" "$pathname"; then
        mv -i "$pathname" "${pathname%.*}.xml"
    fi
done

Começo definindo uma série de opções de shell que normalmente não são definidas bashpor padrão:

  • globstarativa o **padrão globbing que corresponde recursivamente aos subdiretórios.
  • dotglobfaz com que os padrões globais correspondam a nomes ocultos.
  • nullglobfaz com que um padrão não correspondente desapareça completamente, em vez de permanecer sem expansão. Isso garante que nosso loop posterior não será executado se não houver correspondência.
  • extglobhabilite padrões globbing estendidos, por exemplo, @(txt|data|conf)que correspondam a uma das strings entre parênteses.

Em seguida, percorremos os nomes dos candidatos e testamos cada um para a string fornecida. Se a string for encontrada, o arquivo será renomeado substituindo o sufixo do nome do arquivo após o último caractere de ponto por xml.

informação relacionada