
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 grep
e for
entã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 echo
quando estiver convencido de que está fazendo a coisa certa).
grep -RlZ
gera uma lista delimitada por nulos dos nomes dos arquivos onde as correspondências são encontradasxargs -0
passa essa lista separada por nulos parash -c
for f
percorre os nomes dos arquivos como parâmetros posicionais
ou (se você tiver permissão para usar while
em vez de for
), você pode pular xargs
o 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 .txt
extensões .data
e .conf
verifica se a string que você forneceu está presente em cada um deles. Se sim, então a extensão será alterada .xml
por um mv
comando.
Se não tiver certeza se o código funcionará conforme o esperado, você pode adicionar um echo
before mv
para 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 bash
por padrão:
globstar
ativa o**
padrão globbing que corresponde recursivamente aos subdiretórios.dotglob
faz com que os padrões globais correspondam a nomes ocultos.nullglob
faz 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.extglob
habilite 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
.