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

[gelöst] bash und Leerzeichen

ich hänge an einem Problem mit einem bash script, wenn ich wild cards wie "*.jpg" benutze. Vielleicht habt ihr einen Lösungstipp für mich. Darum geht's:

- hab ein Verzeichnis mit Dateien, die teilweise Leerzeichen im Namen haben
- möchte ein Skript schreiben, dass Thumbs von den enthaltenen jpgs erstellt (mit mogrify)
- wenn ich den skript Parameter "*.jpg" verwende, erhalte ich die Liste der Dateinamen, jeweils getrennt durch eine Leerzeichen
- im Skript kann ich nicht mehr feststellen, ob die Leerzeichen ein Trennzeichen sind oder Teil des Dateinamens

Was ich noch gefunden habe ist die option "-b" des Kommandos "ls", bei dem die Leerzeichen "escaped" werden. In diese Richtung geht ja vielleicht die Lösung.

Gibt es eine Möglichkeit, dass "*.jpg" als eine "escaped" Folge an das Skript weiter gegeben wird oder wird das ganz anders angegangen?
 
Ich denke, meistens läßt man sich die Dateinamen in so einem Fall zeilenweise ausgeben, wie es etwa "ls -1" tut. Man verwendet dazu aber besser "find", z.B.:
Code:
for i in $(find -maxdepth 1 | grep "jpg$")
do
    echo $i
done
Ich persönlich verwende aber lieber Python (oder Perl), weil die keine Probleme mit Leerzeichen (oder Subshells) haben und Dateinamen einfach in einer praktischen Liste speichern würden.

Gruß
 
A

Anonymous

Gast
gorgonz schrieb:
- möchte ein Skript schreiben, dass Thumbs von den enthaltenen jpgs erstellt (mit mogrify)

du bist dir aber vollkommen bewußt das mogrify in 95% der möglichen Anwendungen die Orginaldatei ersetzt, du dir also die Orginale zerstörst. Ansonsten convert benutzen, je nach dem was du mit den Thumbs machen willst eventuell auch gleich montage

Notfalls noch mal hier schnell vorbeischauen.

robi
 
@abgdf: Vielen Dank für die schnelle Reaktion! Merke jetzt, dass ich meine Frage vielleicht nicht klar genug gestellt habe. Ich möchte von aussen die Möglichkeit offen halten, eine bestimmte Auswahl von Bildern über wildcards zu bestimmen, die dann im skript verarbeitet werden.

@robi: Hey robi, das ist wirklich brenzlig! Habs schon gemerkt und kopier derzeit vorher die Bilder erstmal in einen thumb Ordner. Hab jetzt statt mogrify convert genommen, schaffe es jedoch nicht, zwei Dateinamen mit convert voneinander zu trennen.

Einen Schritt bin ich inzwischen weiter: Es ist möglich, die Dateinamen erfolgreich in das Skript zu schaffen, indem im Skript nicht $@ verwendet wird, sondern "$@". Zusammen mit dem abgdf Schnipsel und dem Umstieg auf den Vorschlag von robi (convert) klappt alles, solange ich den Code mit echo ausgebe, nicht jedoch als Kommando. Ein Skript Beispiel, wo ich inzwischen angelangt bin:

Code:
if [[ ! -e preview ]]; then
{
  mkdir preview
} fi

for i in "$@"
do
  echo convert -resize 200 $i preview/$i
  # geht natürlich nicht, weil die Leerstellen in den Dateinamen als Parametertrenner gesehen werden

  convert -resize 200 \"$i\" \"preview/$i\"
  # da hab ich gedacht, es müsste gehen, die Hochkommas haben leider nix gebracht
done
 
A

Anonymous

Gast
Wenn du unbedingt mit Argumenten für das Script arbeiten willst, dann versuche mal folges.
Code:
#!/bin/bash
SIZE="200x200"
THRUMB_DIR="./thrumb"


# Deinen Kram

if [ -d "$THRUMB_DIR" ]
   then
     echo "$THRUMB_DIR existiert schon"
else
     mkdir "$THRUMB_DIR"
fi

for i in "$@"
do
file -i "$i" |cut -d ":" -f2 | grep "image/" &>/dev/null
if [ $? -ne 0 ]
   then
        echo "$i ist kein Bilddatei oder existiert nicht"
else
   echo "$i"
   convert "$i" -resize "$SIZE" "$THRUMB_DIR"/"$i"
fi
done

Ist ein bischen abgesichert, falls hier beim Aufruf keine Bilddateien als Argumente kommen, oder sonst wie höchst-seltsame Dateinamen oder Argumente dabei sein sollten.
Aufruf könnte dann zB wie folgt erfolgen.
Code:
./script.sh Bild.jpg Bild2.jpg Bild.png Bild.tiff 
./script.sh  *jpg
cd /home/bilder; /home/user/bin/script.sh *

Nicht gehten tut aber zB
Code:
./sript.sh /home/bilder/*
Dazu müsste der Dateiname erst noch vorher mit "basename" bearbeitet werden, oder die benötigten Unterverzeichnisse dazu angelegt werden.
Also ungefähr so hier
Code:
....
else
   echo "$i"
   FILENAME=$(basename "$i")
   convert "$i" -resize "$SIZE" "$THRUMB_DIR"/"$FILENAME"
fi
Ich befürchte nur das es bei Absoluter Adressierung in der Art "/home/bilder/*" wohl von der Bash aber nicht mehr unterstützt wird und dann wirklich dir Argumentenliste /home/bilder/*" genommen wird. Hilft nur Ausprobieren.

Aber Vorsicht die Argumentenliste für das Script ist begrenzt, aber frag mich jetzt nicht wo, muss ich auch erst nachschauen. Also 100tausend Bilder mit einem Aufruf wird jedenfalls nichts.

robi
 
gorgonz schrieb:
for i in "$@"
do
echo convert -resize 200 $i preview/$i
# geht natürlich nicht, weil die Leerstellen in den Dateinamen als Parametertrenner gesehen werden

convert -resize 200 \"$i\" \"preview/$i\"
# da hab ich gedacht, es müsste gehen, die Hochkommas haben leider nix gebracht
done
Vielleicht solltest Du sie nicht mit Backslash versehen, also:
Code:
convert -resize 200 "$i" "./preview/$i"
Gruß
 
@abgdf: Oh Mann, ich war so nah dran. Klar das wars! Skript funktioniert :D

@robi: Das mit dem file Kommando raff ich heute nicht mehr, ist schon zu spät/früh heute ;) . Aber beim Anlegen des Unterverzeichnisses hast Du recht. Ich hab daher auch noch ein Abbruchkriterium aufgenommen, wenn es eine Datei mit dem Namen des Unterverzeichnisses gibt.

hier noch mal meine heutige Fassung, falls jemand grad mal so was auf die Schnelle braucht:

Code:
#!/bin/bash
# resize pictures in a directory and save it in the subdirectory preview
# syntax: make_thumb default|geometry file_spec
# where
# geometry is <width>x<height> or the string "default", which results in 195x146 pixel. It is a mandatory parameter!
# file_spec is a pattern to define the wanted pictures, examples: *.jpg or p201104*.png

# preset the name for the thumbs subdir 
thumb_dir="preview"

# set the size of the thumbs 
if [[ $1 == "default" ]]; then {
  size=195x146
}
else {
  size=$1
} fi
shift

# create the directory preview, if it doesn't exist
if [[ -d ${thumb_dir} ]]; then {
  echo ${thumb_dir} already exists!
}
else {
  if [[ -f ${thumb_dir} ]]; then {
    echo "ERROR, there is a file with the name of the thumb directory: ${thumb_dir}"
    exit 1
  }
  else {
    mkdir ${thumb_dir}
  } fi
} fi

# create the thumbs
for i in "$@"
do
  echo processing $i
  convert -resize ${size} "$i"  "${thumb_dir}/$i"
done

Was noch offen ist:

- das mit "file"
- wie robi schon geschrieben hat: das Skript versagt, wenn mein working dir nicht der Ordner der Bilder ist. Dann häng ich nämlich das subdir vorn dran, wo es doch hinten vor dem Namen des Bildes kommen muss. Wenn da einer was Praktisches hat, nehm ich das gerne!

gute nacht!
 
gorgonz schrieb:
Dann häng ich nämlich das subdir vorn dran, wo es doch hinten vor dem Namen des Bildes kommen muss. Wenn da einer was Praktisches hat, nehm ich das gerne!

Dann wäre es evtl. hilfreich, wenn du das Verzeichnis vor dem Namen des Bildes verwenden würdest bzw die Varaible thumb_dir, am Anfang des Scriptes, den passenden Pfad setzt.
 
@robi: erst jetzt war ich wieder klar genug, um Deine Ideen zu verstehen ;-) file und Pfadgeschichten sind aufgenommen.

Vielen Dank an Euch Alle für die reichhaltige und konstruktive Unterstützung. Kann mich nur revanchieren, indem ich den aktuellen Stand wieder der Community zurückgebe. Als kleiner Komfort ist noch ein --verbose spendiert.

Code:
#!/bin/bash

# preset the name for the thumbs subdir and the size 
thumb_dir="preview"
size=195x195
verbose=0

if [[ $1 == "--help" ]]; then {
  echo Aufruf: `basename "$0"` [--help] [--size geometry] [--verbose] [DATEI1] ... [DATEIn]
  echo Erzeugt thumbs von Datei1 ... DATEIn in der Größe geometry, Ziel ist Unterverzeichnis "${thumb_dir}",
  echo wobei wildcards in den Dateinamen erlaubt sind, also *.jpg oder /home/bilder/p2011*.png.
  echo
  echo Über die Option --help kann diese Hilfe aufgerufen werden
  echo Über die Option --size kann die Standardgröße "${size}" der thumbs abgeändert werden
  echo                 geometry ist ein Ausdruck vom Typ "BILDBREITExBILDHÖHE" in Pixeln
  echo Über die Option --verbose können ausführlichere Meldungen aktiviert werden
  exit
} fi

# set the size of the thumbs 
if [[ $1 == "--size" ]]; then {
  if [[ $# -ge 2 ]]; then {
    size=$2
    shift 2
  }
  else {
    echo ERROR: Missing parameter for --size
    exit 1
  } fi
} fi

if [[ $1 == "--verbose" ]]; then {
  verbose=1
  shift
} fi

if [[ ${verbose} == 1 ]]; then {
  echo set thumb size= ${size} pixel
  echo set thumb dir = ${thumb_dir}
} fi

if [[ $# == 0 ]]; then {
  echo No files defined, nothing to do
  exit
} fi

# create the directory preview, if it doesn't exist
if [[ -d ${thumb_dir} ]]; then {
  echo ${thumb_dir} already exists!
}
else {
  if [[ -f ${thumb_dir} ]]; then {
    echo "ERROR: there is a file with the name of the thumb directory: ${thumb_dir}"
    exit 1
  }
  else {
    mkdir ${thumb_dir}
  } fi
} fi

# create the thumbs
for i in "$@"
do
  file -i "$i" |cut -d ":" -f2 | grep "image/" &>/dev/null
  if [[ $? -ne 0 ]]; then {
    if [[ ${verbose} == 1 ]]; then {
      echo "$i ignored (no pic)"
    } fi
  }
  else {
    echo processing $i
    dirname=`dirname "$i"`
    basename=`basename "$i"`
    convert -resize ${size} "$i"  "${dirname}/${thumb_dir}/${basename}"
  } fi
done
 
Oben