
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 grep
und for
dann 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, echo
sobald Sie zufrieden sind, dass es das Richtige tut).
grep -RlZ
gibt eine durch Nullen getrennte Liste der Namen von Dateien aus, in denen Übereinstimmungen gefunden wurdenxargs -0
übergibt diese null-getrennte Liste ansh -c
for f
durchläuft die Dateinamen als Positionsparameter
while
oder (wenn Sie anstelle von verwenden dürfen for
) können Sie xargs
und 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, find
ist in diesem Zusammenhang angemessener. Es sucht rekursiv nach regulären Dateien mit den Erweiterungen .txt
, .data
und .conf
und prüft, ob die von Ihnen angegebene Zeichenfolge in jeder davon vorhanden ist. Wenn ja, wird die Erweiterung .xml
durch einen mv
Befehl in geändert.
Wenn Sie nicht sicher sind, ob der Code wie erwartet funktioniert, können Sie ein „ echo
Vorher“ 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
bash
Ich beginne mit dem Festlegen einer Reihe von Shell-Optionen, die normalerweise nicht standardmäßig festgelegt sind :
globstar
aktiviert das**
Globbing-Muster, das Unterverzeichnisse rekursiv abgleicht.dotglob
sorgt dafür, dass Globbing-Muster mit versteckten Namen übereinstimmen.nullglob
lä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.extglob
Aktivieren 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
.