Cambie el nombre del archivo usando grep y for

Cambie el nombre del archivo usando grep y for

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 grepy forluego 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 echouna vez que esté satisfecho de que está haciendo lo correcto).

  • grep -RlZgenera una lista delimitada por nulos de los nombres de los archivos donde se encuentran coincidencias

  • xargs -0pasa esa lista separada por nulos ash -c

  • for frecorre los nombres de archivos como parámetros posicionales

o (si se le permite usar whileen lugar de for) puede omitir xargsel 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 findes más adecuado en este contexto. Busca recursivamente archivos normales con .txtextensiones .datay .confcomprueba si la cadena que proporcionaste está presente en cada uno de ellos. En caso afirmativo, cambiará la extensión .xmlmediante un mvcomando.

Si no está seguro de si el código funcionará como se espera, puede agregar un echoantes mvpara 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 bashde forma predeterminada:

  • globstarhabilita el **patrón global que coincide en subdirectorios de forma recursiva.
  • dotglobhace que los patrones globales coincidan con nombres ocultos.
  • nullglobhace 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.
  • extglobhabilite 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.

información relacionada