Was ist eine effektive Möglichkeit, Dateierweiterungen automatisch an Dateien ohne Erweiterung anzuhängen?

Was ist eine effektive Möglichkeit, Dateierweiterungen automatisch an Dateien ohne Erweiterung anzuhängen?

Ich habe heute während meiner Mittagspause ein Bash-Skript geschrieben, das in einem Verzeichnis nach Dateien ohne Erweiterung sucht und diesen Dateien eine Dateierweiterung anhängt.

Das Skript ist relativ lang, weil ich eine Menge Flags und Sachen wie Verzeichnisauswahl hinzugefügt habe und ob die Datei kopiert oder überschrieben werden soll, aber die grundlegende Funktionalität kann einfach wie folgt repliziert werden:

#recursively find files in current directory that have no extension
for i in $(find . -type f ! -name "*.*"); do
    #guess that extension using file
    extfile=$(file --extension --brief $i)
    #select the first extension in the event file spits something weird (e.g. jpeg/jpe/jfif) 
    extawk=$(echo $extfile | awk -F/ '{print $1}')
    #copy the file to a file appended with the extension guessed from the former commands
    cp -av $i $i.$extawk
done

In meinem eigentlichen Skript ist es etwas ordentlicher – ich wollte die Befehle hier nur aufteilen, damit ich kommentieren kann, warum ich Dinge mache.

Meine Frage: Die Verwendung findin Kombination mit filein der von mir gewählten Weise ist wahrscheinlich nicht die sicherste Methode, dies zu tun – was ist dieam bestenMöglichkeit, Erweiterungen für eine große Gruppe unterschiedlicher Dateitypen in mehreren Verzeichnissen rekursiv zu erraten und anzuhängen?

Antwort1

for x in $(find …)scheitert mitDateinamen, die Leerzeichen (häufig) oder Platzhalterzeichen (eher ungewöhnlich) enthalten. Analysieren Sie niemals die Ausgabe von find. Verwenden Sie -exec.

Zsh'Szmvist praktisch für die Massenumbenennung.

Lassen Sie uns einen zmv-Befehl konstruieren, der das tut, was Sie wollen. Lassen Sie uns zuerst das Suchmuster erstellen:

autoload zmv
zmv -C -o -a -n -Q '(*/)#^*.*(.)' …
  • -Cbewirkt, dass Dateien kopiert statt verschoben werden.
  • -o -ageht über -aan cp.
  • -nbedeutet, nicht zu handeln, sondern nur zu drucken, was getan werden soll. Entfernen Sie es, wenn Sie zufrieden sind. Ersetzen Sie es durch „ -vwenn Sie handeln, aber auch drucken möchten, was getan wird“.
  • -QermöglichtGlob-Qualifikationim Muster.
  • (*/)#trifft auf null oder mehr Verzeichnisse zu. Es verwendet die# Glob-Operator( extended_globist in zmv immer aktiviert).
  • ^*.*verwendet den Glob-Operator, um Dateien ohne „a“ im Namen ^abzugleichen ..
  • (.)ist ein Glob-Qualifizierer, der die Übereinstimmungen auf reguläre Dateien beschränkt.
  • wird durch den Ersatztext ersetzt. Dieser kann verwendet werden, $fum auf den Originalnamen zu verweisen.

zmvberechnet alle Ersatznamen, bevor ein Ersatz durchgeführt wird, und meldet sich, wenn bereits ein Ersatzname vorhanden ist oder es Konflikte gibt. Dateien, deren Ersatzname mit dem Original identisch ist, werden übersprungen.

Lassen Sie uns nun den Ersatztext erstellen. Wir werden viel verwendenParametererweiterungMerkmale.

  1. fileVerlängerung beantragen :$(file --extension --brief -- $f)
  2. .Stellen Sie zur Vorbereitung des Ersatzes ein voran : $(echo -n .; file --extension --brief -- $f)
    (Dies könnte alternativ mit der Parametererweiterung erfolgen: ${:-.$(…)}.)
  3. Wenn mehrere vorgeschlagene Erweiterungen (durch Schrägstriche getrennt) vorhanden sind, behalten Sie nur die erste:${$(echo -n .; file --extension --brief -- $f)%%/*}
  4. Wenn die vorgeschlagene Erweiterung leer oder ist ???, geben Sie auf (ersetzen Sie .oder .???durch eine leere Zeichenfolge):${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}
  5. Hängen Sie die hinzugefügte Erweiterung an $f(den ursprünglichen Namen) an. Wenn das, was wir anhängen, leer ist, bleibt die Datei unverändert.

Der resultierende Befehl:

zmv -C -o -a -n -Q '(*/)#^*.*(.)' '$f${${$(echo -n .; file --extension --brief -- $f)%%/*}:#.(|\?\?\?)}'

Dies ist etwas kryptisch und Sie ziehen es möglicherweise vor, den Code zum Generieren des Ersatzes in eine Funktion einzufügen und zu verwenden zmv … '$(add_extension $f)'.

Antwort2

Der effektivste Weg besteht meiner Meinung nach darin, die MIME-Typen der Datei mit der Datenbank unter zu vergleichen /usr/share/mime/globs.

  • Klumpenin Linux sindDateierweiterung. Beispiel angegeben, Ausgabe vonGlobs-Datei
application/x-mswinurl:*.url
text/x-mrml:*.mrl
text/x-erlang:*.erl
audio/x-pn-audibleaudio:*.aa
application/x-bzip-compressed-tar:*.tbz2
application/x-netshow-channel:*.nsc
application/x-hdf:*.h4
application/pgp-keys:*.key
text/x-idl:*.idl
text/x-chdr:*.h
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.ms-powerpoint.presentation.macroEnabled.12:*.pptm
application/vnd.visio:*.vsd
application/x-hdf:*.h5
video/vnd.mpegurl:*.m4u
  • nach der Beschreibung des Typs example --> text/x-erlangweist es Linux an, alle Dateien *.alsErlangmit der Erweiterung .erl[glob], deshalb -->*.erl
  • /etc/magicSie können Ihre eigenen Erweiterungen hinzufügen, die in der Datei berücksichtigt werden

Führen Sie daher den folgenden Befehl aus:

mimetype -bM file
  • bArgument für „zeig es dir einfach type-app/extension“ (kurz)

  • MArgument bedeutetMagieist die Art und Weise, wie Linux die Dateien im Bytecode, hexadezimal und binär prüft, um zu verifizieren, dass die Dateien wirklich das sind, was sie vorgeben zu sein.

  • Mime Typgibt nicht /jpg/png/webpnur einen Typ zurück und dieser ist kürzer alsfile --mime-type file

Kehrt zurück:

image/webp

abschließende Gedanken

mimetypefunktioniert am besten mitBinärdateienwie PDFs, Bilder, Videos. Das liegt daran, dass es die Binärdatei prüfen kann, anstatt text plainnur das zu tun, und Sie müssen sich mit etwas identifizieren, und das ist komplizierter, deshalb können Texteditoren verschiedene Programmiersprachen erkennen, es braucht die Hilfe des Benutzers und eine Serversprache für jede Programmiersprache.

für Rekursion, denke ichBaumist gut:

tree -FIi '*.*' | grep -v /$
  • Argument ist , [Schrägstrich] zu Verzeichnissen Fhinzuzufügen , Beispiel, →/folderfolder/
  • Argument Iist, das Gegenteil des Musters auszuwählen *.*[das heißt, alle Dateien mit der Erweiterung auszuwählen], also ist das Gegenteil nicht die Erweiterung
  • Das Argument ibesteht darin, Leerzeichen aus der Baumausgabe zu entfernen
  • grep -vist die Auswahl umgekehrt, deshalb fügen Sie das /Argument -F hinzu zuBaumBefehl am Anfang, damit Sie Verzeichnisse entfernen und nur Dateien abrufen können, mit /$.

Weitere Informationen finden Sie hierMIME-Typen

verwandte Informationen