• Willkommen im Linux Club - dem deutschsprachigen Supportforum für GNU/Linux. Registriere dich kostenlos, um alle Inhalte zu sehen und Fragen zu stellen.

bash test auf datei geht nicht [fast gelöst]

OsunSeyi

Hacker
Hi,
Code:
	PATH_NEW=`echo $PATH_OLD | sed "s|$EXCLUDED_PATHS||g"`

	echo  $PATH_NEW						# ergibt korrekt '/home/tom/file'
	file $PATH_NEW						# findet die Datei
	cat $PATH_NEW						# funktioniert ebenfalls.

	if [ -f "$PATH_NEW"  ] ; then echo 'x' ; fi		# hingegen ergibt keine Ausgabe

Wie kann das sein, und wie kann ich das Problem vermeiden?
Hat das vielleicht mit dem Zeichensatz vom Script zu tun, daß da noch Steuerzeichen im String sind?
 

uhelp

Member
Glaub ich nicht.
Das funktioniert so.

Irgendetwas hast du übersehen hier mitzuteilen.
Kannst ja mal das vollständiges Script posten.
 
file dient nicht dem Finden von Dingen sondern gibt aus um was für eine Art von file es sich handelt. Dort steht dann nicht zufällig was von symbolischer Link oder ähnliches?
 
OP
OsunSeyi

OsunSeyi

Hacker
Code:
  EXCLUDED_PATHS='/mnt/hd/sda4/DAT/D/BAK/SCR/BIN/SL-12.2/MySQL/sql-update-tour'

	PATH_OLD='/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour /mnt/hd/sda4/DAT/D/BAK/SCR/BIN/SL-12.2/MySQL/sql-update-tour'

	PATH_NEW=`echo $PATH_OLD | sed "s|$EXCLUDED_PATHS||g"`

	if [ -f "$PATH_NEW" ] ; then echo 'x' ; fi

	echo $PATH_NEW
	file $PATH_NEW

Ausgabe:

Code:
~ | LifeDoc-SRC
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour: POSIX shell script, ISO-8859 text executable

müsste aber eigentlich sein:

Code:
~ | LifeDoc-SRC
x
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour: POSIX shell script, ISO-8859 text executable

'ls $PATH_NEW' funktioniert auch normal!

Kein symbolischer Link!
Bin ich verrückt?

Gegenprobe:
Das selbe ohne Einsatz von 'sed':

Code:
	PATH_NEW='/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour'

	if [ -f "$PATH_NEW" ] ; then echo 'x' ; fi

	echo $PATH_NEW
	file $PATH_NEW
	ls $PATH_NEW

Code:
~ | LifeDoc-SRC
x
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour: POSIX shell script, ISO-8859 text executable
/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour

Nur mal so, das unten klappt wiederum:
Da wird der zweite Pfad auch entfernt, alles ab dem Leerzeichen.

Code:
	PATH_OLD='/mnt/hd/sda4/DAT/D/BIN/MySQL/sql-update-tour /mnt/hd/sda4/DAT/D/BAK/SCR/BIN/SL-12.2/MySQL/sql-update-tour'

	PATH_NEW=`echo $PATH_OLD | sed "s| .*$||g"`


	if [ -f "$PATH_NEW" ] ; then echo 'x' ; fi  # Ausgabe ist jetzt 'x'
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Code:
 EXCLUDED_PATHS='/home/tom/file2'

    PATH_OLD='/home/tom/file1 /home/tom/file2'

   PATH_NEW=`echo $PATH_OLD | sed "s|$EXCLUDED_PATHS||g"`

   if [ -f "$PATH_NEW" ] ; then echo 'x' ; fi			# klappt nicht
Code:
 EXCLUDED_PATHS=' /home/tom/file2'

    PATH_OLD='/home/tom/file1 /home/tom/file2'

   PATH_NEW=`echo $PATH_OLD | sed "s|$EXCLUDED_PATHS||g"`

   if [ -f "$PATH_NEW" ] ; then echo 'x' ; fi			# klappt!

Der Unterschied ist, das bei "EXCLUDET_PATHS" das Leerzeichen mit angegeben ist:
EXCLUDED_PATHS=' /home/tom/file2'

Das ist mir jetzt aber vollkommen neu, weil mW bisher immer alle Variablen Leerzeichen am Anfang oder Ende vom String nicht übernehmen!
:???:
 

MH1962

Member
Was ist jetzt eigentlich genau Dein Problem?

Wenn $PATH_NEW mit einem Leerzeichen beginnt (was beim sed übrig geblieben ist) UND im if-Statement gequotet wird, wird das Leerzeichen als Teil des Dateinamens angesehen und eine solche Datei wird mit Recht nicht gefunden.

Also kannst Du ENTWEDER das Leerzeichen mit abschneiden, was Du ja in dem einen Beispiel machst ODER auf die Quotes um die Variable im if-Statement verzichten. Beides funktioniert.
 
OP
OsunSeyi

OsunSeyi

Hacker
Ich hatte angenommen, daß generell führende und abschließende Leerzeichen nicht in Variablen übernommen werden...
Deine Antwort leuchtet ein, hab's gerade überprüft.

Darüber hinaus hatte ich angenommen, if-'test' würde meckern, wenn eine leere Variable ohne doppelte Anführungszeichen übergeben wird,
aber auch das ist im Fall '-f' oder '-d' offensichtlich nicht der Fall.

Danke für die Hilfe!

PS

Code:
	TESTPATH=''
		if [ -d $TESTPATH -o -f $TESTPATH ] ; then echo 'x' ; fi

ergibt 'x' als Ausgabe, was für mich überaschend (und irreführend) ist :schockiert:

So gesehen wäre eine eindeutigere Methode, um die Gültigkeit eies Pfades zu prüfen, wünschenswert.
Gibt es da nicht was?

Alleine dieses "if [ -d $TESTPATH -o -f $TESTPATH ]" nervt doch schon...

Code:
	if [ -f $PATH_NEW    -o -d $PATH_NEW   ] ; then TEST_PATH='x' ; fi

	if [ -z "$TEST_PATH" -o -z "$PATH_NEW" ] ; then
	...
Das obige kann doch nicht die Lösung sein???
 
OP
OsunSeyi

OsunSeyi

Hacker
In Hinblick auf eine evtl. leere Variable besser, aber eine Abfrage auf Gültigkeit des Pfades ist damit immer noch ungeschickt ist.
Muss leider zur Arbeit, auf die Schnelle klappt fogendes nicht...

Code:
	test='/home/tom'

	if [[ -d "$test" -o -f "$test" ]] ; then echo 'x' ; fi

Wenn ich die Gültigkeit mit 'ls' prüfe, wird es auch komplizierter, weil 'ls' auch auf mehrere Pfadangaben reagiert.
Man will schließlich wissen, og es sich um genau einen gültigen Pfad handelt!
 

uhelp

Member
Dir fehlt ein prizipielles Verständnis des Quotens. Lies mal das hier: http://www.grymoire.com/Unix/Quote.html

Code:
var=eins zwei drei   # CommandNotFoundError; die "eins" landet in der Variable,
#  das Kommando "zwei" mit seinem Argument "drei" wird nicht gefunden.
var="eins zwei drei"   #OK. Durch Quoting sieht die Bash den String "eins zwei drei" (Ohne Anführungszeichen)

# eine Hilfsfunktion, die die Anzahl aller Argumente ausgibt und dann die Argumente eines pro Zeile
# Die Argumente werden in <> eingeschlossen.
print_args(){    
   echo es wurden $# Argumente angegeben; 
   for ((i=1;i<=$#;i++)) ; do  
      printf "ArgNo: %-3s Arg: <%s>\n" $i "${!i}"; 
   done
}

# set -- arg1 arg2
# setzt die aktuellen Argumentzeile. Hier auf "arg1 arg2" ohne Anführungszeichen
set -- $var
print_args $*  # die Argumente müssen mit übergeben werden

set -- $var "drei vier fünf" LetztesArgument
print_args $*
# sieht so aus, als wäre alle gleich
# aber:
printf "<$1> <$2> <$3> <$4> <$5> <$6> <$7> <$8> <$9> <${10}> <${11}> <${12}>\n"
# Das ist passiert, weil der Aufruf von printf selbst wieder von der Bash geparst werden muss, 
# und damit wieder nach Leerzeichen in Tokens geteilt wird (genauer nach der IFS (InternalFieldSeparator) Variablen gesplittet wird.

var="BEGINN"
var2=ENDE
set -- $var " Leerzeichen auch am Anfang und Ende "   $var2
print_args $*
printf "<$1> <$2> <$3> <$4> <$5> <$6> <$7> <$8> <$9> <${10}> <${11}> <${12}>\n"

# wir schreiben jetzt die ganze Argumentzeile ( BEGINN  Leerzeichen auch am Ende  ENDE ) iin eine Variable
all_args="$*"
set -- $all_args
print_args $*
printf "<$1> <$2> <$3> <$4> <$5> <$6> <$7> <$8> <$9> <${10}> <${11}> <${12}>\n"

# Die Leerzeichen am Anfang und Ende sind weg.
# Weil die bash Leerzeichen als Trenner sieht, wenn sie die Zeile set -- $all_args ausführt.
Langer Rede, kurzer Sinn: du willst (fast) immer jede Expanison, wie $var als "$var" schreiben.

Du musst auch nicht auf directory oder file prüfen.
Es genügt auf -exists oder -writable zu prüfen.
 
OP
OsunSeyi

OsunSeyi

Hacker
Vielen Dank für die ausführliche Antwort und die Bemühung!
Da werde ich noch einiges zu lernen haben...
Für den Augenblick hat der Test '-e' auf jeden Fall schon viel weitergeholfen!
 
Oben