[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: mehrere Dateinamen in einer Variablen an Programm übergeben



Am Dienstag, 27. August 2013, 20:43:16 schrieb Matthias Meyer:
> Hallo,

Hi Matthias,

> Ich habe ein Problem mit einem bash-script dem ich mehrere Dateinamen als
> Parameter übergeben will und die Dateinamen können natürlich BLANKS
> enthalten.
> Das test-script:
> #$!/bin/bash
> while test $# -gt 0; do
>     echo :$1:; shift
> done
> exit
> 
> Das funktionert wenn ich die Dateinamen direkt angebe:
> %scripts/test 'file1' 'file name'
> 
> :file1:
> 
> :file name:
> Wenn ich die Dateinamen aber in einer Variablen halte dann geht es nicht
> mehr
> 
> filenames="'file1' 'file name'"
> %scripts/test $filenames
> 
> :'file1':
> :'file:
> 
> :name':

Für Diagnose-Zwecke:

martin@merkaba:~ -> cat test
#$!/bin/bash
echo "Anzahl: $#"
echo "Zeile:  $*"
while test $# -gt 0; do
        echo :$1:; shift
done
exit


Okay, auch mit Escaping geht es nicht:


martin@merkaba:~ -> filenames="\"file1\" \"file name\""


In der Bash:

martin@merkaba:~ -> ./test "file1" "file name"
Anzahl: 2
Zeile:  file1 file name
:file1:
:file name:
martin@merkaba:~ -> ./test $filenames
Anzahl: 3
Zeile:  "file1" "file name"
:"file1":
:"file:
:name":



Das heißt, die Bash löst das Quoting nicht auf, wenn die Argumente als 
Variable daher kommen. Interessant.


Hier würde jetzt

martin@merkaba:~ -> for DATEI in "file1" "file name" ; do echo "$DATEI"; done
file1
file name

funktionieren.

Das funktioniert bei direkter Übergabe aber nicht, da die Bash das Quoting 
dann auflöst und die Anführungszeichen dann nicht mehr in $* mit drinnen sind.


Und warum die Bash sich so verhält, steht wahrscheinlich irgendwo in der 
wunderbaren Manpage der Bash.


Die Z-Shell verhält sich anders:

martin@merkaba:~ -> zsh
martin@merkaba:~> ./test "file1" "file name"
Anzahl: 2
Zeile:  file1 file name
:file1:
:file name:

martin@merkaba:~> filenames="\"file1\" \"file name\""
martin@merkaba:~> ./test $filenames                  
Anzahl: 1
Zeile:  "file1" "file name"
:"file1" "file name":


Sie betrachtet offenbar den Variablen-Inhalt als *ein* Argument, IMHO 
konsistenter, sinniger als das, was die Bash macht.


> Wie kann ich eine Liste von Dateinamen in einer Variablen sammeln und dann
> an ein anderes Programm übergeben?

Wenn Du immer mit einer Variable arbeitest, funktioniert das For-Schleifen-
Dingens, zumindest mit der Bash.


Irgendwie zeigt mir obiges Beispiel mal wieder, dass ich komplexere Dinge 
nicht als Shell-Skript realisieren möchte.

Allerdings hängt das gar nicht mal davon ab. Ein Ruby-Skript macht genau den 
gleichen Müll. Es bekommt das Zeug schon so von der Bash:

martin@merkaba:~ -> cat ./test.rb
#!/usr/bin/env ruby
puts $*

martin@merkaba:~ -> ./test.rb eins zwei
eins
zwei
martin@merkaba:~ -> ./test.rb $filenames
"file1"
"file
name"


Das ganze in der Z-Shell:

martin@merkaba:~> filenames="\"file1\" \"file name\""
martin@merkaba:~> ./test.rb $filenames
"file1" "file name"

Wieder als ein Argument.


So mal sehen, vielleicht hat ja jemand eine logische Erklärung für das 
Verhalten der Bash. Das Verhalten der Z-Shell leuchtet mir ja noch irgendwie 
ein.

Es läßt sich mit der Bash auch hinbekommen:

martin@merkaba:~ -> ./test.rb "$filenames"
"file1" "file name"


LOL.

Jetzt lasse ich das erstmal sitzen. Die Erklärung ist bestimmt ganz logisch :) 
– innerhalb von Shell-Logik :)

Ciao,
-- 
Martin 'Helios' Steigerwald - http://www.Lichtvoll.de
GPG: 03B0 0D6C 0040 0710 4AFA  B82F 991B EAAC A599 84C7


Reply to: