Bash, Suchmuster im Dateinamen und vergleiche es

0

Ich versuche, eine Datei basierend auf einem Muster über Bash Script zu verschieben.

Ich verwende find, um alle meine Camcorder-Dateien und das Bestandsergebnis in TXT File auszuwählen.

Jede meiner Camcorder-Dateien enthält das Jahr. Ich würde gerne Grep oder etwas anderes verwenden, um diese Zeichenfolge zu finden (Jahr mit 4 Ziffern, dh 1984) und diese Zeichenfolge vergleichen, um die Datei in einen anderen Ordner zu verschieben. Wenn die Datei nach 1984 ist, muss meine Datei gehe in den Ordner "Marie", wenn die Datei vor oder nach 1984 ist, muss sie in den Ordner "Marie_Liam" gehen.

Ich habe verschiedene Dinge versucht, mit Grep und während read -r line, aber wenn ich gefundene Zeichenfolge (Jahr) vergleiche, kehre mein Skript jedes Mal nach 1984 zurück ...

Hier sind meine anderen Versuche:

Ich habe verschiedene Dinge wie dieses ausprobiert (es sind viele Versuche, nicht nur ein Skript):

Basisskript:

#!/bin/bash
find /home/CamFiles/ -name "*.m2ts"

Versuch 1:

TestScriptResultFile="/home/Dio/CamCorderFindResult.file"
do
  if [ grep -e " 1984 " "$in" ];
  then
    echo "Voici un film qui est avant 1984 $FindMovie"
  else
    echo "Voici un film qui est de 1984 : $FindMovie"
  fi;
done

-- Noch ein Versuch --

while IFS= read -r line; do
  if [[ /bin/grep -E "[1][9][8][4]" "$MyLine" != 0 ]] ;
  then
    echo "Ok"
  fi
done < "$TestScriptResultFile"
while read line; do
  if  echo "$line" | grep -q "[1][9][8][4]"; then echo "$line"; fi
  Found=$(echo "$line" | grep -q "[1][9][0-8][0-4]")
  if [[ " $Found " <= 1984 ]]; then echo "$line"; fi
done < "$TestScriptResultFile"
exit 0

-- Noch ein Versuch --

while read MyLine
do
  if grep -E "$MyPattern" "$MyLine"
  then
    echo "tourne apres 1984 : $MyLine"
  else
    echo "Tourne avant 1984 : $MyLine"
  fi
done < "$TestScriptResultFile"

Danke für Ihre Hilfe.

Freundliche Grüße.

Dio
quelle
Ich habe meinem ursprünglichen Beitrag
Dio
Ich denke, alle Ihre Dateien enthalten Zeichenfolge 1984. Um exifinfo zu lesen, ist es besser, exiftooloderexiftran
Ipor Sircer
Dies kann ohne diese Informationen geschehen, aber es wäre viel einfacher, wenn Sie ein paar Zeilen mit den Namen Ihrer Dateien schreiben, um zu zeigen, wo das Jahr erscheint. Wenn seine Position konstant ist, ist die Lösung kurz und offensichtlich.
Gombai Sándor
Das Jahr ist nicht die einzige Zeichenfolge. In einigen Dateien habe ich die lokale Postleitzahl (wo der Film aufgenommen wurde) oder ein Datum, das die Aufenthaltsdauer angibt, und in einigen Dateien habe ich kein Datum. t use media tag, alle meine Dateien wurden von einem Server-RAID 6-Absturz (elektrischer Blitz) wiederhergestellt, und meine Dateien sind für einige korrupt und für alle ohne Tags ... Also muss ich Dateinamen verwenden, um zu bestellen, wie es vor dem war Absturz ...
Dio

Antworten:

0

Ich habe die Skripte basierend auf den in Ihrem Kommentar angegebenen Dateinamenbeispielen aktualisiert:

"Liam sur la moto (VHS) (2001) - Maison 13100.m2ts" 
"M&L Plage 1080i (2012) - Camargue 30240.m2ts

Ich habe mir zwei Methoden ausgedacht, um diese Namenskonvention zu handhaben.

Die erste ist anzunehmen, dass das Jahr in jedem Fall in Klammern steht. Ich habe das 'erste' Skript aktualisiert, um diesen Fall widerzuspiegeln. Es ist einfach eine Aktualisierung des verwendeten Regex-Musters.

regexPat='\(\K[0-9]{4,4}(?=\))'

Das zweite Skript wurde aktualisiert, um eine andere Methode zu zeigen, bei der wir nicht sicher sein können, ob das Jahr in Klammern steht. Hier lesen wir das Ergebnis der grep-Auswertung als Array aus, falls es mehrere Übereinstimmungen gibt, und führen dann eine Überprüfung des Jahres durch - dh das Jahr muss zwischen 1970 und 2020 liegen; Ansonsten nehmen wir an, dass es kein Jahr ist.


Beachten Sie, dass der readarrayBefehl (auch Mapfile genannt) nur in Bash-Versionen 4.x + verfügbar ist. Am unteren Rand ist eine tragbare Version mit nur read. Es kann schwierig sein , die Ausgabe zu analysieren, findohne dass aufgrund von Leerzeichen oder Sonderzeichen in den Dateinamen Fehler auftreten.

Skript 1


#!/bin/bash
# Create test files
touch abcd\({2001,1985,1984,1931}\)efgh.m2ts
touch abcd{24001,198a5,19b84,1912331,1293}.m2ts
touch "abcd 1232 adffd.m2ts"
touch "Liam sur la moto (VHS) (2001) - Maison 13100.m2ts"
touch "M&L Plage 1080i (2012) - Camargue 30240.m2ts" 
TestScriptResultFile="./CamCorderFindResult.file"
touch $TestScriptResultFile

regexPat='\(\K[0-9]{4,4}(?=\))'

readarray fileList <<<"$(IFS="\n" ; find . -name "*.m2ts" -exec basename {} \;)"
for i in "${fileList[@]}"; do 
  echo "Processing File: $i"
  if year=$(grep -oP "$regexPat" <<<"$i");    then
    if [ "$year" -le 1984 ]; then
      echo "1984 or earlier: $i" >> "$TestScriptResultFile"
    else
      echo "After 1984: $i" >> "$TestScriptResultFile"
    fi
  else
    echo "No valid year found in file $i"
  fi
done

1. Verwenden Sie den findBefehl, um eine Dateiliste abzurufen und mit ein Array zu speichern readarray.

  • Setzen Sie den Feldtrenner auf eine neue Zeile: IFS=$'\n'
  • Verwenden Sie ein -execArgument, finddas basenamefür jede Datei ausgeführt wird, um nur den Dateinamen und nicht den Pfad abzurufen.
  • Das findAusgangssignal wird in ein Array gerichtet durch die Verwendung Befehls Substitution und A ‚ Hier String‘ , <<<und den readarrayBefehl

2. Durchlaufen Sie das Array mit den Dateinamen

3. Verwenden Sie grep und regexPat, um das eingebettete Jahr zu finden

  • Das Regex-Muster, das ich verwendet habe, stimmt mit 6 Zeichen in einer Zeichenfolge überein, wenn das erste Zeichen ein a ist (, gefolgt von genau 4 Zahlen [0-9]{4,4}und abgeschlossen durch ein a )am Ende.

  • Um nur die 4 Zahlen dazwischen (hoffentlich das Jahr) auszugeben, wird das Argument -Pgegeben, nach 'Perl Regex' zu suchen, wodurch unter anderem übereinstimmende Zeichen von erfassten (Ausgabe-) Zeichen getrennt werden können.

  • Das /Kwird dazu führen, dass grep nichts ausgibt, was vor dem /Kin dem Muster übereinstimmt (auch bekannt als Look-Ahead ).
  • Schließlich wird das Schließen )aus der Ausgabe entfernt, indem ein Look-Behind-Non-Capture verwendet wird, das dem ähnelt /K. Sie können für beide dieselbe Syntax verwenden. Das untere Skript zeigt die Look-Ahead-Methode, die nicht verwendet wird /K.

  • Das -oFlag weist grep an, nur den erfassten, übereinstimmenden Teil der Zeichenfolge auszugeben, in unserem Fall eine 4-stellige Zahl.

Der Rest des Skripts prüft die Nummer gegen 1984 und protokolliert sie entsprechend.


Hier ist ein weiterer kompakterer Ansatz.

2 Dinge, die hier zu beachten sind

  • findwird das Argument gegeben, -print0das die Ausgabe beendet.
  • Der readBefehl erhält das Argument -d '', das angibt, dass seine Eingabe mit Null beendet ist. Eine Nullzeichenfolge wird normalerweise \0im Klartext geschrieben . in Bash können Sie ''oder verwenden$'\0'

Skript 2


#!/bin/bash

TestScriptResultFile="./CamCorderFindResult.file"
touch $TestScriptResultFile

regexPat='(?<=[^0-9])[0-9]{4,4}(?=[^0-9])'
find . -name "*.m2ts" -print0 | while IFS= read -r -d '' k; do
  i="$(basename "$k")"
   echo "Processing File: $i"
     if year=($(grep -oP "$regexPat" <<<"$i")); then
     for yr in "${year[@]}"; do
       if [ "$yr" -lt 1970 ] || [ "$yr" -gt 2020 ]; then
         echo "   x Out of range year ($yr) parsed from $i"
       else
         echo "   o Found year $yr"
         if [ "$yr" -le 1984 ]; then
           echo "1984 or earlier: $i" >> "$TestScriptResultFile"
         else
           echo "After 1984: $i" >> "$TestScriptResultFile"
         fi
      fi
     done
   else
     echo "   x No valid year found in file $i"
  fi
done
Argonauten
quelle
Hallo Agonauten, ein ganz großes Dankeschön für dein Drehbuch! Ich habe jeden ausprobiert und keiner arbeitet wie erwartet, der erste ist für jede erste Ziffer gesperrt, also wenn meine Datei 02-1980 oder 720i für das Camcorder-Format nicht verarbeiten kann: Dio @ Dio: ~ #: ./StackOverFlow.sh: Zeile 11: [: 1986 720: Integer-Ausdruck erwartet Verarbeitungsdatei: "Liam sur la moto (VHS) (2001) - Maison 13100.m2ts" ./StackOverFlow.sh: Zeile 11: [: 2001 1080: Integer-Ausdruck erwartet Verarbeitungsdatei : "M & L Plage 1080i (2012) - Camargue 30240.m2ts" ./StackOverFlow.sh: Zeile 11: [: 2012 1080: Integer-Ausdruck erwartet
Dio
Ich musste die Methode zur Benennung von Dateien erraten. Veröffentlichen Sie einige vollständige Beispiele der Namen und ich werde sicherstellen, dass es mit ihnen funktioniert.
Argonauten
Ok, danke, Sie können unten ein paar meiner Dateinamen sehen: Liam & Marie - Noel (1999) (DVR) Maison.avi Liam 1985 - Etang (VHS) 84120.mp4 Marie - 1979 VHS Chez Francois.mp4 Marie - 1979 - Premiere Noel Maison (VHS) .mp4 Liam - 1er Match de Foot (1991) (720i) .avi Liam - Jahr der offenen Tür (2006) (1080p) .m2ts Vacances en Famille 2004 - (1080p) .m2ts L & M Chez Tonton 12-02-1993 vhs.avi Marie remise diplome (1999) .avi Ich habe auch einige Dateien, die in .mkv und .webm sind. Sie wurden vor einigen Jahren selbst erstellt, wenn sie wie andere sortiert werden können, wäre es schön ! Danke für Ihre Hilfe !
Dio
Ich denke, dass das 2. Skript für diese Dateien effektiv sein sollte; Für die anderen Erweiterungen müssen Sie die find-Anweisung anpassen. Wenn Sie nicht weiterkommen, schreiben Sie eine Antwort.
Argonauten
Skript funktioniert nicht: x In der Datei abcd1912331.m2ts wurde kein gültiges Jahr gefunden. Verarbeitungsdatei: abcd1293.m2ts x In der Datei abcd1293.m2ts wurde kein gültiges Jahr gefunden. Verarbeitungsdatei: abcd 1232 adffd.m2ts x In der Datei abcd 1232 adffd wurde kein gültiges Jahr gefunden .m2ts-Verarbeitungsdatei: Liam sur la Moto (VHS) (2001) - Maison 13100.m2ts x In der Datei Liam sur la Moto (VHS) (2001) - Maison 13100.m2ts-Verarbeitungsdatei: M & L Plage 1080i (2012) wurde kein gültiges Jahr gefunden ) - Camargue 30240.m2ts x Kein gültiges Jahr in Datei gefunden M & L Plage 1080i (2012) - Camargue 30240.m2ts
Dio