Schlagwort-Archive: programmierung

Leerzeichen bei For-In-Schleifen in der bash

Im Artikel Dateinamen mit Leerzeichen auf der Kommandozeile verarbeiten habe ich beschrieben, wie man Ärger mit Leerzeichen in Dateinamen umgeht. Heute geht es um Daten, die innerhalb einer For-In-Schleife aus einer Datei gelesen werden und die Leerzeichen enthalten.

Wenn wir eine Datei mit folgendem Inhalt haben:

klaus rechner1
martin rechner3
dieter rechner7

Und wir lassen diese von folgendem Script einlesen und wieder ausgeben (was natürlich recht sinnfrei ist, hier aber nur zur Veranschaulichung dienen soll):

#!/bin/bash
for ZEILE in `cat daten`
do
  echo $ZEILE
done

Dann kommt sowas raus:

klaus
rechner1
martin
rechner3
dieter
rechner7

Durch die Leerzeichen werden die Daten-Zeilen zerteilt. Damit das nicht passiert, setzt man den „Input Field Separator“ $IFS auf ‚\n‘ (Standard ist ein “ \n\t“):

#!/bin/bash
Newline=$'\n'
IFS=$Newline
for ZEILE in `cat daten`
do
echo $ZEILE
done
IFS=

Dann sieht das Ergebnis wie erwartet und gewünscht aus:

klaus rechner1
martin rechner3
dieter rechner7

Mercurial Tipps & Tricks

Seit einiger Zeit bin ich auf das Verteilte Versionskontrollsystem Mercurial umgestiegen. Es bietet einige Vorteile gegenüber altbekannten Systemen wir z.B. CVS. Aber darauf will ich hier nicht eingehen, sondern einige Tipps und Tricks vorstellen, die den täglichen Umgang mit hg vereinfachen.

Push und Update des Ziels in einem

Mit hg push werden die Änderungen des eigenen Repositories in das Eltern-Repo hochgeladen. Dort werden die Änderungen aber nur im Repository eingetragen, das Arbeitsverzeichnis wird aber nicht aktuallisiert. Dies muss normalerweise per Hand mit einem hg update im entsprechenden Verzeichnis erfolgen. Beim Pull-Befehl gibt es den Schalter -u, der ein Update nach dem Pull ausführt – leider gibt es das nicht für das Push-Kommando.

Aber es gibt zwei Möglichkeiten, um diesen Schritt einzusparen (und vor Allem nicht zu vergessen):

Ausführen von Push und Update in einem Befehl

Man kann bei Linux & Co. die Ausführung von mehreren Kommandos auf einer Zeile bewirken, in dem man die Kommandos mit „&&“ verbindet. Außerdem kann man bei hg über den Parameter -R ein Repository angeben, in dem der Befehl ausgeführt werden soll. Somit lässt sich der Push und das Update des Ziel-Repositories verbinden:

  hg push && hg -R pfad_zum_ziel_repository update

Dazu muss man aber den Pfad des Ziels kennen. Dies lässt sich mit hg path ermitteln. Es spricht aber auch nichts dagegen, das direkt auf der Kommandozeile zu integrieren:

  hg push && hg -R `hg path | awk -F = '{ print $2; }'` update

Am Besten legt man sich einen Alias dafür an, in dem man z.B. folgendes in die .bashrc einträgt:

  pushup () { hg push && hg -R `hg path | awk -F = '{ print $2; }'` update ; }

Dann braucht man nur noch pushup eingeben, um ein Push mit nachfolgendem Update des Eltern-Repository zu machen.

Automatisches Update bei jedem Push

Unter 4.15. Any way to ‚hg push‘ and have an automatic ‚hg update‘ on the remote server? in den Mercurial-FAQs ist ein weiterer Weg beschrieben, wie man erzwingt, das bei einem Push auch ein Update des Ziels erfolgt. Dieses Verfahren hat aber aus meiner Sicht zwei Nachteile:

  1. Es wird immer ein Update gemacht, man kann es nicht „mal eben“ ausschalten. Bei der oben beschriebenen Lösung kann man immer den original hg push Befehl ausführen, wenn man gerade nicht will, dass ein Update durchgeführt wird.
  2. Die Änderung wirkt nur in dem Repository, in dem es in die hgrc eingetragen wurde. Arbeitet man in einem anderen Repository (z.B. eines anderen Projektes), in dem diese Änderung nicht durchgeführt wurde, kann das zu Verwirrungen führen, wenn man gewohnt ist, dass ein Push auch ein Update auslöst.

Die beschriebene Lösung über Hooks hat natürlich auch Vorteile (z.B. kann wirklich keiner das Update vergessen) und schlussendlich muss jeder selbst entscheiden, welchen Weg er beschreiten möchte.

Gibt es Unterschiede zwischen Repository und Working-Directory?

Klar, wenn man selbst Änderungen durchgeführt hat, kann man das über hg status erkennen. Was aber, wenn man ein hg pull oder ein hg push auf das Repository ausführt hat (Es kann ggf. auch jemand anderes ein Push auf „mein“ Repository gemacht haben, wenn er die Rechte dazu hat)? Dann hilft ein hg status nicht weiter. Ob es Unterschiede gibt, kann man aber mit

  hg diff -r tip

herausfinden. Will ich nur wissen ob und welche Dateien betroffen sind, verwende ich

  hg diff -r tip | grep '^diff'

Gibt es Änderungen im Eltern-Repository?

Auch hier gibt hg status keine Auskunft. Aber mit hg incoming (oder kurz: hg in erfahren wir, was es an Änderungen gibt, die bei einem Pull übertragen würden. Will ich wissen, welche Dateien sich ändern, setze ich den Schalter -v hinten an.

Ein Verzeichnis mit allen Unterverzeichnissen hinzufügen

Führt man hg add ./images/* aus, so werden nur die Dateien im Verzeichnis ./images hinzugefügt, nicht aber die Dateien, die sich in weiteren Unterverzeichnissen tummeln. Hier kann man sich mit find helfen:

  hg add `find ./images -type d -printf '%p/* '`