Dateien rekursiv mit Sonderzeichen bearbeiten.

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
swar0g
Beiträge: 289
Registriert: 12.12.2002 22:07:17
Wohnort: Hannover

Dateien rekursiv mit Sonderzeichen bearbeiten.

Beitrag von swar0g » 17.02.2006 15:32:37

Ich brauche so ein Skript, der wie folgt aussieht

Code: Alles auswählen

for file=$( find -maxdepth 3 -name blabla ) ;  do 
 newfile = $file $( echo $file | sed s/.alteendung/.neueendung/g )
 befehl $file $newfile
done
Wobei das Problem ist, das in den Dateinamen es regelrecht von Sonderzeichen wimmelt, auch in den Verzeichnisnamen, die ja recursiv abgearbeitet werden.

Also kommen sehr häufig Klammern, Leerzeichen und " ' in den Dateinamen vor.

Wie geht man am besten vor?
d3 d0 c1 d3 c9 20 cd c9 d2 2c 20 d5 c2 c5 ca 20 d3 c5 c2 d1 0a

roli
Beiträge: 3174
Registriert: 10.09.2003 17:39:58

Re: Dateien rekursiv mit Sonderzeichen bearbeiten.

Beitrag von roli » 17.02.2006 19:12:32

Hi,

Code: Alles auswählen

for file in $( find -maxdepth 3 -name blabla )
  do 
   newfile=$( echo $file | sed s/.alteendung/.neueendung/g )
   befehl $file $newfile
done
wenn du in der "for" Zeile aus dem "=" ein "in" machst, sollte es schon fast gehen. Jetzt noch die newfile Zeile aendern (siehe oben) und ich denke, das ist es was du suchst, oder?
Roland


"Aber wenn du schon so unwissend bist, davon noch nicht gehört zu haben,
so will ich es doch als gut ansehen, daß du lieber einmal töricht fragst,
als weiterhin nichts von etwas zu wissen, das man doch wissen sollte."
aus "Die Edda des Snorri Sturluson", "Gylfis Täuschung"

Methusalix

Dateien rekursiv mit Sonderzeichen bearbeiten.

Beitrag von Methusalix » 17.02.2006 19:45:53

Hallo,

von dem = Zeichen mal abgesehen: mit Deinem Befehl änderst Du per sed ja nur die Dateiendung (wenn nicht mehrere Punkte im Dateinamen vorkommen). Wo sind den die Sonderzeichen? Sonderzeichen müssen gegebenenfalls mit sed gequotet werden.
Auch Leerzeichen kannst Du mit sed filtern.

bedeutet: befehl
mv $file $newfile
? (was ja Sinn machen würde)?

Vielleicht solltest Du mal einen repräsentativen (soweit vorhanden) Dateinamen posten.

Gruß
Matthias

Benutzeravatar
swar0g
Beiträge: 289
Registriert: 12.12.2002 22:07:17
Wohnort: Hannover

Re: Dateien rekursiv mit Sonderzeichen bearbeiten.

Beitrag von swar0g » 17.02.2006 19:52:05

roli hat geschrieben:Hi,

Code: Alles auswählen

for file in $( find -maxdepth 3 -name blabla )
  do 
   newfile=$( echo $file | sed s/.alteendung/.neueendung/g )
   befehl $file $newfile
done
wenn du in der "for" Zeile aus dem "=" ein "in" machst, sollte es schon fast gehen. Jetzt noch die newfile Zeile aendern (siehe oben) und ich denke, das ist es was du suchst, oder?
nein, mir geht es um um was ganz Anderes. Vergessen wir den kleinen Fehler in der for-Schleife.

Ich möchte rekursiv die Festplatte nach bestimmten Dateien durchsuchen und den Dateinamen als Argument einem xbeliebigen Programm übergeben.

Du wirst z.B. sehr schnell feststellen, dass so ein Script überhaupt nicht funktionieren wird, sobald in dem Dateinamen Leerzeichen auftreten.

Generell macht man dies mit
find -print0 -name bla ./ | xargs -0 progname

Jetzt stell dir ein Programm vor, das nur eine Datei als Argument bekommen kann. Da muss man sich schon was Neues einfallen lassen. Genau vor so einem Problem stehe ich gerade.
d3 d0 c1 d3 c9 20 cd c9 d2 2c 20 d5 c2 c5 ca 20 d3 c5 c2 d1 0a

Benutzeravatar
swar0g
Beiträge: 289
Registriert: 12.12.2002 22:07:17
Wohnort: Hannover

Re: Dateien rekursiv mit Sonderzeichen bearbeiten.

Beitrag von swar0g » 17.02.2006 19:59:27

Matthias-GE hat geschrieben:Hallo,

von dem = Zeichen mal abgesehen: mit Deinem Befehl änderst Du per sed ja nur die Dateiendung (wenn nicht mehrere Punkte im Dateinamen vorkommen). Wo sind den die Sonderzeichen? Sonderzeichen müssen gegebenenfalls mit sed gequotet werden.
Auch Leerzeichen kannst Du mit sed filtern.

bedeutet: befehl
mv $file $newfile
? (was ja Sinn machen würde)?

Vielleicht solltest Du mal einen repräsentativen (soweit vorhanden) Dateinamen posten.

Gruß
Matthias
z.B. mv

Nehmen wir an, ich habe ich eine CD mit Musikarchiv bekommen. Nun, da sind nur ogg Dateien drin, die fälschlicherweise eine .mp3 Endung bekamen. Unzällige Ordner mit verrücktesten Dateinamen:

blad_blaa blaa'.mp3
blaa_blaa $$$$sososos'''' """".mp3
sosos__???****++**haha.mp3


Es gilt die umzubenennen.


Es ist nur ein Beispielproblem, ich möchte eigentlich keine Dateien umbenennen und ich weiß, das es mächtigere Tools als mv gibt - z.B mmv.
d3 d0 c1 d3 c9 20 cd c9 d2 2c 20 d5 c2 c5 ca 20 d3 c5 c2 d1 0a

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 17.02.2006 21:00:54

wir erzeugen zwei "schmutzige" Dateien und erstellen eine Funktion "printarg1"

Code: Alles auswählen

gms@gms1:~/tmp/test$ mkdir " dir mit blanks "
gms@gms1:~/tmp/test$ cd " dir mit blanks "/
gms@gms1:~/tmp/test/ dir mit blanks $ touch " file mit blanks "
gms@gms1:~/tmp/test/ dir mit blanks $  touch ' file mit quote " ' 
gms@gms1:~/tmp/test/ dir mit blanks $ cd ..
gms@gms1:~/tmp/test$ printarg1() { echo $1; } 
dann schauen wir uns an was mit "normaler" for-schleife passiert:

Code: Alles auswählen

gms@gms1:~/tmp/test$ for file in $(find -type f -name "*"); do printarg1 "$file"; done
./
dir
mit
blanks
/
file
mit
blanks

./
dir
mit
blanks
/
file
mit
quote
"
mit IFS temporär umgesetzt schauts besser aus:

Code: Alles auswählen

gms@gms1:~/tmp/test$ IFS=$'\n' 
gms@gms1:~/tmp/test$ for file in $(find -type f -name "*"); do IFS=" ";printarg1 "$file"; done
./ dir mit blanks / file mit blanks
./ dir mit blanks / file mit quote "
gms@gms1:~/tmp/test$ IFS=" " 
mit einer pipe zu einer while schleife schauts auch gut aus:

Code: Alles auswählen

gms@gms1:~/tmp/test$  find -type f -name "*" | while read file; do printarg1 "$file"; done
./ dir mit blanks / file mit blanks
./ dir mit blanks / file mit quote "
Gruß
gms

[edit]
IFS geändert von IFS="" zu IFS=$'\n'
[/edit]
Zuletzt geändert von gms am 17.02.2006 22:16:18, insgesamt 1-mal geändert.

ToPeG
Beiträge: 437
Registriert: 14.04.2004 00:42:06

Beitrag von ToPeG » 17.02.2006 21:15:59

Noch kann es bei "Sonderzeichen" zu Problemen kommen ($& usw.) Wenn man sie auskommentiert umgeht man das.

Code: Alles auswählen

file=`echo $file | sed -e 's/\([^a-zA-Z0-9_-\.~]\)/\\\\\1/g;`

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 17.02.2006 21:59:05

wieso soll es durch Sonderzeichen zu Problemen kommen:

Code: Alles auswählen

gms@gms1:~/tmp/test$ cd " dir mit blanks "/
gms@gms1:~/tmp/test/ dir mit blanks $ touch ' file mit & '
gms@gms1:~/tmp/test/ dir mit blanks $ touch ' file mit $ ' 

Code: Alles auswählen

gms@gms1:~/tmp/test$ lsarg1() { ls -ld "$1"; } 
gms@gms1:~/tmp/test$ IFS=$'\n' 
gms@gms1:~/tmp/test$ for file in $(find -type f -name "*"); do IFS=" ";lsarg1 "$file"; done
-rw-r--r--  1 gms gms 0 2006-02-17 20:26 ./ dir mit blanks / file mit blanks
-rw-r--r--  1 gms gms 0 2006-02-17 20:56 ./ dir mit blanks / file mit quote "
-rw-r--r--  1 gms gms 0 2006-02-17 21:17 ./ dir mit blanks / file mit &
-rw-r--r--  1 gms gms 0 2006-02-17 21:17 ./ dir mit blanks / file mit $
@swar0g
der IFS im vorhergehenden Posting wurde falsch gesetzt, hier ist er richtig mit IFS=$'\n'
entspricht also dem Newline; und du hast hoffentlich keine Dateien, die ein Newline enthalten


Gruß
gms

ToPeG
Beiträge: 437
Registriert: 14.04.2004 00:42:06

Beitrag von ToPeG » 18.02.2006 01:38:46

Weil eine Datei "rm -Rv * > test.txt" zu einem Problem führen könnte wenn man sie in in `` setzt? Sicher wenn man Anführungszeichen verwendet kann man das umgehen, aber nicht immer ist das möglich. (z.B. wenn der Dateiname selbst Anführungszeichen enthält)

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 18.02.2006 12:58:50

ToPeG hat geschrieben:Weil eine Datei "rm -Rv * > test.txt" zu einem Problem führen könnte wenn man sie in in `` setzt? Sicher wenn man Anführungszeichen verwendet kann man das umgehen, aber nicht immer ist das möglich. (z.B. wenn der Dateiname selbst Anführungszeichen enthält)
Das einzige Sonderzeichne welches hier Probleme machen würde, wäre ein "Newline" und das nur wegen der Zerlegung für die For-Schleife
Weder eine Datei "rm -Rv * >test.txt", noch andere Sonderzeichen die du auch erwähnt hast, wie Anführungszeichen, '$' und '&' führen zu einem Problem:

Code: Alles auswählen

gms@gms1:~/tmp/test$ touch ' dir mit blanks '/'rm -Rv * >test.txt'
gms@gms1:~/tmp/test$ lsarg1() { ls -ld "$1"; }
gms@gms1:~/tmp/test$ IFS=$'\n' 
gms@gms1:~/tmp/test$ for file in $(find -type f -name "*"); do IFS=" ";lsarg1 "$file"; done
-rw-r--r--  1 gms gms 0 2006-02-17 20:26 ./ dir mit blanks / file mit blanks
-rw-r--r--  1 gms gms 0 2006-02-17 20:56 ./ dir mit blanks / file mit quote "
-rw-r--r--  1 gms gms 0 2006-02-18 12:50 ./ dir mit blanks / file mit quote '
-rw-r--r--  1 gms gms 0 2006-02-17 21:17 ./ dir mit blanks / file mit &
-rw-r--r--  1 gms gms 0 2006-02-17 21:17 ./ dir mit blanks / file mit $
-rw-r--r--  1 gms gms 0 2006-02-17 22:27 ./ dir mit blanks /- file with minus
-rw-r--r--  1 gms gms 0 2006-02-18 12:46 ./ dir mit blanks /rm -Rv * >test.txt
Gruß
gms

init 0
Beiträge: 673
Registriert: 21.10.2003 19:40:28

Beitrag von init 0 » 18.02.2006 13:06:07

Meiner Meinung nach sollte man irgednwann doch die Bash Geschichten lassen.
Python, Perl, Ruby oder sogar PHP als Scriptsprachen bieten so viele Möglichkeiten.
Ach ja, und nix schrotten.
Ich habe einen schlechten Stil, ich weiss, Danke, wurde mir bereits gesagt.

Antworten