Ach, lol hab mich vertan. Ich hab jetzt vdf mit vtf verwechselt. Hättest das nicht erklären müssen. War noch nicht so ganz wach.
Ich hab zur Zeit ein ganz anderes Problem. Ich möchte mir mit einer Funktion einen Teil für den Befehl find zusammenbasteln. Oben trägt man nur die Dateitypen ein. Man kann die Dateien zwar erst alle suchen und dann greppen, was letzendlich bei vielen Dateierweiterungen länger dauert. Um das ganze zu optimieren, habe ich halt diese Funktion geschrieben:
|
Source code
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
bz2include() {
if [ $# = 1 ]; then
echo -n "-name *.$1"
return
fi
output="\( -name \*.$1"
shift
for type in $@; do
output="$output -o -name \*.$type"
shift
done
output="$output \)"
echo -n "$output"
return
}
|
Dann halt festlegen welche Dateien erlaubt werden sollen (ginge natürlich auch anders herum):
|
Source code
|
1
|
bz2_include_filetypes="nav bsp mp3 wav vtf mdl txt"
|
txt-Dateien habe ich absichtlich mit reingenommen, da ich die Funktionalität testen wollte. Gerade beim Globbing der Shell kommen komische Sachen zustande. Wenn Dateien mit der Endung .txt im gleichen Verzeichnis sein, kommt es zum Fehler, da das Globbing der Shell *.txt durch die Dateien ersetzt, die sich im gleichen Verzeichnis befinden. Dadurch wäre der Befehl find -name *.txt ungültig. Man kann entweder das Globbing mit einem Backslash verhindern oder den Text Quotieren ("" oder mit ''). Leider geht das so nur, wenn man das so im Shell-Script direkt eingibt und nicht mit Variablen arbeitet. Hab auch schon Probiert den Find-Befehl in die Funktion mit reinzunehmen und direkt mit der Variable output zu arbeiten.
Hier der Funktionsaufruf, der nicht geht:
|
Source code
|
1
2
|
find $(bz2include $bz2_include_filetypes) #Fehler, wenn ich die Klammern aus der Funktion nehme, geht es
include="$(bz2include $bz2_include_filetypes)"; find $include #Geht natürlich auch nicht.
|
Die Ausgabe sähe so aus:
|
Source code
|
1
|
\( -name \*.nav -o -name \*.bsp -o -name \*.mp3 -o -name \*.wav -o -name \*.vtf -o -name \*.mdl -o -name \*.txt \)
|
In mehreren Versuchen habe ich es auch mal ohne Klammern gemacht, welche die Expression eigentlich nur zusammenfassen:
|
Source code
|
1
|
-name \*.nav -o -name \*.bsp -o -name \*.mp3 -o -name \*.wav -o -name \*.vtf -o -name \*.mdl -o -name \*.txt
|
Hingegen funktioniert dieser Aufruf:
|
Source code
|
1
|
bash -c "find /home/server/bash_test $(bz2include $bz2_include_filetypes)"
|
D.h. wenn ich mit echo oder einer Variable etwas in einem Shell-Script übergebe, wird der Backslash ganz anders interpretiert. Erstelle ich die Datei '*.txt' (Mit Hochkommatas, hatte ja länger rumprobiert), wird diese gefunden. Um sicher zu gehen, habe ich alle drei Varianten getestet. '*.txt', "*.txt" und \*.txt
Mit bash -c "...." funktioniert es, da dort wieder der Backslahs das Globbing verhindert aber nicht vom Befehl find als extra Zeichen mit interpretiert wird.
So, jetzt die große Preisfrage. Wie bekomme ich das Script so hin, dass es funktioniert, ohne den Befehl bash -c verwenden zu müssen. Ich will auch nicht mit grep arbeiten, da es einfach langsamer ist und ich damit nicht das erreiche, was ich eigentlich vorhatte. Mit grep kann doch jeder...
Was ich so witzig finde, dass find -name "*.txt" langsamer ist als find | grep '.txt$'. Nimmt man hingegen mehrere Dateiendungen wird die Ausführungszeit durch grep immer lansgamer, wogegen der Befehl find mit einer recht konstanten Geschwindigkeit sucht.
Ich muss mich jetzt erstmal auf etwas anderes konzentrieren. Wenn man zulange eine Sache macht, dann sieht man irgendwann den Wald vor lauter Bäumen nicht.
EDIT: Ich hab es jetzt erstmal mit grep realisiert
|
Source code
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
#!/bin/bash
bz2_include_filetypes="nav bsp mp3 wav vtf mdl txt"
#bz2_include_filetypes="nav"
bz2include() {
if [ $# = 1 ]; then
grep ".$1$"
return
fi
output=".$1$"
shift
for type in $@; do
output="$output|.$type$"
shift
done
egrep "$output"
return
}
find | bz2include $bz2_include_filetypes| while read file; do
bzip2 -kv $file
done
|