Datei umbenennen mit grep und für

Datei umbenennen mit grep und für

Ich möchte Dateien mit den Erweiterungen .txt, .data, .conf in ".xml" umbenennen

hallo.txt -> hallo.xml

Dazu muss die Datei außerdem folgende Zeile enthalten:<?xml version="1.0" encoding="UTF-8"?>

Das ist, was ich habe:

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

Irgendwelche Ideen?

Antwort1

Wenn dubrauchenum es zu tun grepund fordann vielleicht so etwas?

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

(Entfernen Sie es, echosobald Sie zufrieden sind, dass es das Richtige tut).

  • grep -RlZgibt eine durch Nullen getrennte Liste der Namen von Dateien aus, in denen Übereinstimmungen gefunden wurden

  • xargs -0übergibt diese null-getrennte Liste ansh -c

  • for fdurchläuft die Dateinamen als Positionsparameter

whileoder (wenn Sie anstelle von verwenden dürfen for) können Sie xargsund das zusätzliche Shell-Scriptlet überspringen, wie

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

Antwort2

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 {} +

Ich denke, findist in diesem Zusammenhang angemessener. Es sucht rekursiv nach regulären Dateien mit den Erweiterungen .txt, .dataund .confund prüft, ob die von Ihnen angegebene Zeichenfolge in jeder davon vorhanden ist. Wenn ja, wird die Erweiterung .xmldurch einen mvBefehl in geändert.

Wenn Sie nicht sicher sind, ob der Code wie erwartet funktioniert, können Sie ein „ echoVorher“ hinzufügen mv, um zu sehen, was er bewirkt.

Ich sollte auch erwähnen, dass dieses Skript nicht von Nicht-POSIX-Dienstprogrammen abhängig ist.

Antwort3

Sie können Folgendes versuchen:

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

Antwort4

Verwendung von 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

bashIch beginne mit dem Festlegen einer Reihe von Shell-Optionen, die normalerweise nicht standardmäßig festgelegt sind :

  • globstaraktiviert das **Globbing-Muster, das Unterverzeichnisse rekursiv abgleicht.
  • dotglobsorgt dafür, dass Globbing-Muster mit versteckten Namen übereinstimmen.
  • nullgloblässt ein nicht übereinstimmendes Muster vollständig verschwinden, anstatt unaufgeweitet zu bleiben. Dies stellt sicher, dass unsere Schleife später überhaupt nicht ausgeführt wird, wenn es keine Übereinstimmung gibt.
  • extglobAktivieren Sie erweiterte Globbing-Muster, die beispielsweise @(txt|data|conf)mit einer der Zeichenfolgen in den Klammern übereinstimmen.

Wir durchlaufen dann die Kandidatennamen und testen jeden einzelnen auf die angegebene Zeichenfolge. Wenn die Zeichenfolge gefunden wird, wird die Datei umbenannt, indem das Dateinamensuffix nach dem letzten Punktzeichen durch ersetzt wird xml.

verwandte Informationen