
Me gustaría cambiar el nombre de los archivos con las siguientes extensiones: .txt, .data, .conf a ".xml"
hola.txt -> hola.xml
Para hacerlo, el archivo también debe contener la siguiente línea:<?xml version="1.0" encoding="UTF-8"?>
Esto es lo que tengo:
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
¿Algunas ideas?
Respuesta1
Si ustednecesidadpara hacerlo grep
y for
luego tal vez algo como esto?
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
(quítelo echo
una vez que esté satisfecho de que está haciendo lo correcto).
grep -RlZ
genera una lista delimitada por nulos de los nombres de los archivos donde se encuentran coincidenciasxargs -0
pasa esa lista separada por nulos ash -c
for f
recorre los nombres de archivos como parámetros posicionales
o (si se le permite usar while
en lugar de for
) puede omitir xargs
el scriptlet de shell adicional y 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
Respuesta2
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 {} +
Creo que find
es más adecuado en este contexto. Busca recursivamente archivos normales con .txt
extensiones .data
y .conf
comprueba si la cadena que proporcionaste está presente en cada uno de ellos. En caso afirmativo, cambiará la extensión .xml
mediante un mv
comando.
Si no está seguro de si el código funcionará como se espera, puede agregar un echo
antes mv
para ver qué hace.
También debo mencionar que ese script no depende de utilidades que no sean POSIX.
Respuesta3
Puedes probar esto:
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
Respuesta4
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
Empiezo configurando una serie de opciones de shell que normalmente no están configuradas bash
de forma predeterminada:
globstar
habilita el**
patrón global que coincide en subdirectorios de forma recursiva.dotglob
hace que los patrones globales coincidan con nombres ocultos.nullglob
hace que un patrón que no coincide desaparezca por completo, en lugar de permanecer sin expandirse. Esto garantiza que nuestro bucle posterior no se ejecutará en absoluto si no hay ninguna coincidencia.extglob
habilite patrones globales extendidos, por ejemplo,@(txt|data|conf)
que coincidan con una de las cadenas dentro del paréntesis.
Luego recorremos los nombres de los candidatos y probamos cada uno para la cadena dada. Si se encuentra la cadena, se cambia el nombre del archivo reemplazando el sufijo del nombre de archivo después del último punto por xml
.