[Suche] - Hilfe bei der Überarbeitung eines bash-Scripts

Binomico

Binomico

Grünschnabel
Guten Tag allerseits,

ich suche verzweifelt nach einer Lösung für mein Problem. Meine Zielsetzung ist wie folgt:

Ich möchte in einem Verzeichnis rekursiv alle Dateien (falls möglich auch Ordner), auf die die Definition zutrifft ändern, eben per bash.

Definition:
ich.bin.die.s12.beispieldatei.xml > Ich.Bin.Die.S12.Beispieldatei.xml
ich.BIN.auch.eine.beispieldatei.xml > Ich.BIN.Auch.Eine.Beispieldatei.xml

Nun das Script funktioniert, was die Dateien in dem Verzeichnis angeht, in dem es ausgeführt wird, perfekt. Die rekursive Auflistung ist das Problem! Mit find hab ich es nicht geschafft ... :/ dazu sei gesagt, dass ich gerade die ersten Schritte mit unixbasierten Betriebssystemen/Scripten mache :-)

Code:
#!/bin/bash
for FILE in `ls -1`
do
NUMBEROFDOTS=`echo ${FILE} | gawk '{split($0,myarray,".") ; print asort(myarray)}'`
  if([ ${NUMBEROFDOTS} -eq 1 ]) then
      echo "!! Invalid filename: ${FILE}"
  else
      LASTDOT=`expr ${NUMBEROFDOTS} - 1`
      FILENAME=`echo ${FILE} | cut -d "." -f -${LASTDOT}`
      EXTENSIONOLD=`echo ${FILE} | cut -d "." -f ${NUMBEROFDOTS}`
      EXTENSIONNEW=`echo ${EXTENSIONOLD} | gawk '{print tolower($0)}'`
      if([ ${EXTENSIONOLD} == "sh" ]) then
          continue 2;
      else
           mv "${FILENAME}.${EXTENSIONOLD}" "`echo $FILENAME | perl -pe 's/(^|\.)([a-z])/$1\u$2/g;'`.${EXTENSIONNEW}"
      fi
  fi
done

Viele Grüße
 
Wenn du rekusiv suchen möchtest, warum dann das?
Code:
for FILE in `ls -1`
Vorschlag:
Code:
for FILE in `ls -R'
 
Hi NoXqs,

leider funktioniert das Script nur mit one file per line, -R gibt folgende Meldung aus


mv: can't rename 'datei.endung': No such file or directory

Grüße
 
Erstmal Dankeschön für deine Hilfe!

1. Alle Dateien, die geändert wurden, haben als Resultat einen kleinen Anfangsbuchstaben, der Rest passt
2. Dateien in Ordnern, die Punkte im Namen haben, wurde nicht geändert

Gruß
 
Mit find bist du ebenfalls in der Lage Befehle auszuführen und die gefundenen Dateien als Parameter anzugeben.

Speicher dein Script ungefähr in dieser Form ab (anpassungspflichtig !):

Code:
#!/bin/bash
FILE = $1
NUMBEROFDOTS=`echo ${FILE} | gawk '{split($0,myarray,".") ; print asort(myarray)}'`
  if([ ${NUMBEROFDOTS} -eq 1 ]) then
      echo "!! Invalid filename: ${FILE}"
  else
      LASTDOT=`expr ${NUMBEROFDOTS} - 1`
      FILENAME=`echo ${FILE} | cut -d "." -f -${LASTDOT}`
      EXTENSIONOLD=`echo ${FILE} | cut -d "." -f ${NUMBEROFDOTS}`
      EXTENSIONNEW=`echo ${EXTENSIONOLD} | gawk '{print tolower($0)}'`
      if([ ${EXTENSIONOLD} == "sh" ]) then
          continue 2;
      else
           mv "${FILENAME}.${EXTENSIONOLD}" "`echo $FILENAME | perl -pe 's/(^|\.)([a-z])/$1\u$2/g;'`.${EXTENSIONNEW}"
      fi
  fi

und führe diesen Befehl hier aus:
Code:
find -type f -exec foo.sh {} \;

"{}" wird während der Laufzeit durch den absoluten Pfad deiner gefundenen Datei ersetzt.
 
Tag Earl,

merci! Sprich find -type f -exec foo.sh {} \; durch find -type f -exec foo.sh /volume1/mein/pfad/ \; ersetzen?

Nur um sicher zu gehen, dass nicht vom root aus alles ersetzt wird.

Grüße
 
[...]Sprich find -type f -exec foo.sh {} \; durch find -type f -exec foo.sh /volume1/mein/pfad/ \; ersetzen?[...]

Nein, die Zeichenkette "{}" wird während der Laufzeit ersetzt, sprich du brauchst es nicht umschreiben.

So wäre es bereits richtig:
Code:
find -type f -exec foo.sh {} \;

Und das "\;" am Ende des Befehles ist zum beenden des "-exec" Parameters.

Als beispiel kannst du auch mal folgendes Versuchen:
Code:
find ~/Bilder -type f -exec cp {} . \;

Es wird dir alle Dateien aus dem Ordner "~/Bilder" in dein aktuelles Verzeichnis kopieren.
 
Nein, die Zeichenkette "{}" wird während der Laufzeit ersetzt, sprich du brauchst es nicht umschreiben.

So wäre es bereits richtig:
Code:
find -type f -exec foo.sh {} \;

Und das "\;" am Ende des Befehles ist zum beenden des "-exec" Parameters.
Okay, habs mittlerweile getestet, aber erhalte folgende Fehlermeldung

find: /volume1/mein/verzeichnis/uppercase.sh: No such file or directory

Aufruf: find -type f -exec /volume1/mein/verzeichnis/uppercase.sh {} \;

Die Datei uppercase.sh ist ausführbar und liegt im Verzeichnis, von dem ich find ausführe.

Gruß
 
Normalerweise lügt das System nicht bei diesen Meldungen:
Also liegt das script "uppercase.sh" nicht in dem Verzeichnis "/volume1/mein/verzeichnis/" oder der ausführende Benutzer hat keine Berechtigung die Datei oder den Pfad dorthin zu lesen.

Wenn du sicher bist, dass das script uppercase.sh in dem Verzeichnis liegt, in dem du den find aufrufst, dann kannst du das auch so aufrufen:
Code:
find -type f -exec ./uppercase.sh {} \;
 
Hundert Prozent und als root angemeldet, die Datei sogar per chmod +x uppercase.sh ausführbar gemacht (für ein möglichen Cronjob).
 
Ist es vielleicht ein NFS-Volume?
Das würde die Probleme mit root erklären.
Mach doch erstmal mal ein
Code:
ls -l /volume1/mein/verzeichnis/
 
Hi,

das Script läuft auf meinem NAS (abgespecktes Debian) ext3. Die Auflistung der Dateien funktioniert (logischer weise, das eingangs gepostete Script läuft schließlich auch, eben nur nicht rekursiv) :-)

Grüßle
 
Ich habe das Script noch einmal getestet.
"tree" ausführen:
Code:
.
|-- ich.BIN.auch.eine.beispieldatei.xml
|-- ich.bin.die.s12.beispieldatei.xml
`-- tmp
    |-- ich.BIN.auch.eine.beispieldatei.xml
    `-- ich.bin.die.s12.beispieldatei.xml

"find" ausführen, das Script liegt im übergeordneten Verzeichnis:

Code:
$ find -type f -exec ../foo.sh {} \;

"tree" ausführen":
Code:
.
|-- ich.BIN.Auch.Eine.Beispieldatei.xml
|-- ich.Bin.Die.S12.Beispieldatei.xml
`-- tmp
    |-- ich.BIN.Auch.Eine.Beispieldatei.xml
    `-- ich.Bin.Die.S12.Beispieldatei.xml
 
Hi,

hat leider nicht funktioniert, kann es an meiner Linux-Version liegen, hab nämlich kein $ ...

Aber ich hab mir was neues gebastelt, das nach drei bis viermaligem Aufrufen funktioniert (Ordner und die darin befindlichen Dateien werden in der Reihenfolge abgearbeitet, so dass der Pfad für die Files nach dem ersten Aufruf nicht stimmt), aber mit zwei drei Schleifen lässt sich das bestimmt lösen. Ist noch nicht perfekt, aber funktioniert erstmal.

Code:
#!/bin/sh
for FILE in `find . -name "[a-z]*"`
do
    mv $FILE `echo $FILE | sed -r 's/(\<.[a-zA-Z])/\u\1/g;s/\.Doc/\.doc/;s/\.Sh/\.sh/'`
done

Der Anfangsbuchstabe und alle Buchstaben nach einem Punkt werden groß geschrieben, die Dateiendung nicht, das gilt auch für Verzeichnisse.
 

Ähnliche Themen

Switche abfragen über Script

NAS-Drive Mount in Bash-Script über crontab

script sshpass

Verschlüsseltes Backup-Script mit rsync

HandbrakeCLI Shell Skript

Zurück
Oben