BASH, why is so F***king difficult

Giorgos Keramidas keramida at ceid.upatras.gr
Mon Nov 12 23:16:39 EET 2007


On 2007-11-12 20:44, Harris Kosmidhs <hkosmidi at laboratorium.gr> wrote:
> Πάντα με παίδευε το bash. Αλλά τώρα έχω μπροστά μου και manual και πάλι
> δε βγάζω άκρη...
>
> Έχω σε ένα φάκελο τους παρακάτω φακέλους:
> Cocteau Twins__Milk_and_kisses
> Muse-Black.Holes.and.Revelations
> Nick_Cave__The First Born Is Dead
> PinkFloyd__Momentary_lapse_of_reason
> PorcupineTree__Yellow_Hedgerow_Dreamscape
> Radiohead__In_rainbows
> RichardWright__Wet_dream
> Tuxedomoon__Divine
>
> Και το εξής script:
>
> #!/bin/bash
>
> until [ -z "$1" ]
> do
>   dir="$1 "
>   #chmod 755 $dir
>   if [ -x ${dir} ];then
>   		echo $dir
>   	fi
>
>   	shift
> done
>
> Το τρέχω και μου βγάζει:
> hkosmidi at desktop:~/mp3$ ./convert.sh *
> ./convert.sh: line 7: [: Cocteau: binary operator expected
> convert.sh
> convert.sh~
> Muse-Black.Holes.and.Revelations
> ./convert.sh: line 7: [: too many arguments
> PinkFloyd__Momentary_lapse_of_reason
> PorcupineTree__Yellow_Hedgerow_Dreamscape
> Radiohead__In_rainbows
> RichardWright__Wet_dream
> Tuxedomoon__Divine
>
> Γιατί; Το dir το όρισα με τα κενά μέσα κάνοντας quoting με "".
> Αν κάνω if [ -x "${dir}" ];then τότε δεν τυπώνεται τίποτε.

Γιατί δεν είσαι προσεκτικός όταν κάνεις χρήση του ${dir}:

Διάβασε το παρακάτω παράδειγμα, και βρες μόνος σου τι έκανα διαφορετικό:

  keramida at kobe:/home/keramida/tmp/kot$ cat -n foo.sh
       1  #!/usr/local/bin/bash
       2  until [ -z "$1" ]; do
       3      arg="$1"
       4      echo "${arg}"
       5      if test -f "${arg}"; then
       6          echo "${arg} ok"
       7      fi
       8      shift
       9  done
  keramida at kobe:/home/keramida/tmp/kot$ ls -ld *' '*
  -rw-rw-r--  1 keramida  users  - 0 Nov 12 23:06 alpha one
  -rw-rw-r--  1 keramida  users  - 0 Nov 12 23:06 beta two
  keramida at kobe:/home/keramida/tmp/kot$ sh foo.sh *
  alpha one
  alpha one ok
  beta two
  beta two ok
  foo.sh
  foo.sh ok
  keramida at kobe:/home/keramida/tmp/kot$

> Τι στο καλό φταίει; Γιατί είναι τόσο δύσκολο να διαχειριστεί το bash
> τα κενά στα filenames;

Δεν είναι.  Απλά θέλει προσοχή.

Κι επιτέλους, γιατί γράφεις σε bash αν σε τσαντίζει;

Γράψε σε Perl, και ενεργοποίησε όλα τα 'taint checks' ώστε να έχεις τον
απόλυτο έλεγχο του τι θεωρείται 'valid' argument:

  keramida at kobe:/home/keramida/tmp/kot$ cat -n foo.pl
       1  #!/usr/bin/perl -Tw
       2
       3  foreach my $arg (@ARGV) {
       4      my $fname = undef;
       5      if ($arg =~ m/([\w\s]*)/) {
       6          # Untaint argument.
       7          $fname = $1;
       8      }
       9      if (defined($fname)) {
      10          print "arg ${fname}\n";
      11      }
      12  }
  keramida at kobe:/home/keramida/tmp/kot$ ./foo.pl *' '*
  arg alpha one
  arg beta two
  keramida at kobe:/home/keramida/tmp/kot$

Γράψε σε Python, για να μπορείς να έχεις αντίστοιχα features, και ίσως
ελαφρώς πιο 'readable' κώδικα, αν προτιμάς αυτό το στυλ:

  keramida at kobe:/home/keramida/tmp/kot$ cat -n foo.py
       1  #!/usr/bin/env python
       2
       3  import re
       4  import sys
       5
       6  for name in sys.argv[1:]:
       7      k = re.match('([\w\s]*)', name)
       8      if k:
       9          print k.string
  keramida at kobe:/home/keramida/tmp/kot$ ./foo.py *' '*
  alpha one
  beta two
  keramida at kobe:/home/keramida/tmp/kot$

Ο,τι κι αν διαλέξεις όμως, πάψε να γκρινιάζεις :P




More information about the Linux-greek-users mailing list