Hi, ich hab hier schon praktische Scripte gesehen für Linux! Ich möchte
gerade eins entwickeln, das 2 Verzeichnisse anhand der Dateinamen
vergleicht, und die Dateien, die nicht gleich sind, in ein drittes
Verzeichnis kopiert.
Wie geht das? Ich hab oft gesehen "for f in... <machwas>" aber ich
brauche ja "for f in b and not in a" :-) Ich hoffe Ihr versteht, was ich
meine... also irgendwie das Gegenteil von "in"
shelly schrieb:> Ich möchte gerade eins entwickeln, das 2 Verzeichnisse anhand der> Dateinamen vergleicht, und die Dateien, die nicht gleich sind, in ein> drittes Verzeichnis kopiert.
So ist das missverständlich.
Wähle bitte die richtige Option:
[ ] die Dateien, die vom Dateinamen her nicht gleich sind
[ ] die Dateien, die gleich heißen, aber vom Datei-Inhalt her
nicht gleich sind
shelly schrieb:> Ah ja die Gänsefüsschen - ich probiere mal
Vielleicht baust Du noch zu Anfang ein
set -e
ein. Dann wird das Script abgebrochen, wenn ein Fehler auftritt.
Beispiel: Wenn das Verzeichnis $a nicht existiert und der cd-Befehl
fehlschlägt, ist es höchst sinnvoll, abzubrechen und nicht
weiterzumachen.
Es klappt noch ncith ganz, weil ich mit relativen Pfaden arbeiten will:
#! /bin/sh
a="./verz1"
b="./verz2"
c="./verz3"
cd "$a"
for j in *
do
if [ ! -f "$b/$j" ]
then
cp "$j" "$c/$j"
fi
done
beim "cp ist er dann schon eins zu tief..
shelly schrieb:> Es klappt noch ncith ganz, weil ich mit relativen Pfaden arbeiten will:
Dann halt so:
1
#! /bin/sh
2
a="dir1"# change here
3
b="dir2"# change here
4
c="dir3"# change here
5
6
set-e
7
pwd=`pwd`# das sind backticks!
8
9
a="$pwd/$a"
10
b="$pwd/$b"
11
c="$pwd/$c"
12
13
cd"$a"
14
for j in*
15
do
16
if[!-f"$b/$j"]
17
then
18
cp"$j""$c/$j"
19
fi
20
done
Wenn alle 3 Ordner relativ zum aktuellen sind und lediglich die Tiefe 1
haben, dann gehts auch so:
1
#! /bin/sh
2
a="dir1"# change here
3
b="dir2"# change here
4
c="dir3"# change here
5
6
set-e
7
8
cd"$a"
9
for j in*
10
do
11
if[!-f"../$b/$j"]
12
then
13
cp"$j""../$c/$j"
14
fi
15
done
Warum mache ich den cd? Damit ich in $j platte Dateinamen habe und
keinen Ordnernamen. Sonst kann man darauf keinen f-Test in einem völlig
anderen Ordner machen bzw. auch der cp würde fehlschlagen. Wenn Du
unbedingt auf den cd-Befehl verzichten willst, dann muss man sich
umständlich mittels basename den Dateinamen ohne Pfad holen. Das erspare
ich mir durch den cd-Befehl.
klatschnass schrieb:> Und die Leerzeichen in der if Bedingung und vor und hinter den eckigen> Klammern sind wichtig!
Ja, denn [ ist ein Programm, das ausgeführt wird, und es erwartet als
letzten Kommandozeilenparameter das ].
shelly schrieb:> Ich dachte er löst das "./" bei der Zuweisung auf in den kompletten> Pfad, tut er aber wohl nicht
Nein, . ist ein relativer Verweis auf das aktuelle Verzeichnis. Warum
sollte da was aufgelöst werden?
Frank M. schrieb:> pwd=`pwd` # das sind backticks!>> a="$pwd/$a"> b="$pwd/$b"> c="$pwd/$c"
Statt sich ein eigenes $pwd zu definieren, kann man auch einfach die
schon vordefinierte Variable $PWD verwenden.
Rolf M. schrieb:> Statt sich ein eigenes $pwd zu definieren, kann man auch einfach die> schon vordefinierte Variable $PWD verwenden.
Kann man, aber $PWD ist ein bashism. bashisms vermeide ich grundsätzlich
- besonders dann, wenn ich jemandem etwas allgemeines erklären will.
Apropos, ich sehe gerade, dass auch die Command Substitution per
$(command) es mittlerwiele in den POSIX-Standard geschafft hat. Nett :-)
Ebenso die Arithmetic Expansion per $((expression)). Sehr löblich. Damit
kann man nun das ewig lästige
i=`expr $i + 1`
zum Inkrementieren einer Variablen etwas eleganter schreiben.
Frank M. schrieb:> Apropos, ich sehe gerade, dass auch die Command Substitution per> $(command) es mittlerwiele in den POSIX-Standard geschafft hat. Nett :-)
Soweit ich weiß, sind die Backticks schon lange "deprecated".
Noch ein Vorschlag, braucht aber die Bash, GNU cp und xargs:
1
#!/bin/bash
2
a="dir1"#changehere
3
b="dir2"#changehere
4
c="dir3"#changehere
5
6
7
comm-23<(cd"$a"&&ls-1)<(cd"$b"&&ls-1)|
8
sed-e"s,^,$a/,"|
9
xargs--no-run-if-emptycp--target-directory="$c"
Zur Erklärung: Vergleiche zwei sortierte Listen, schreibe die Werte, die
nur in der linken Liste vorkommen. Füge am Anfang jeder dieser Zeilen
noch den Quellpfad $a ein. Kopiere alles genannte in das Zielverzeichnis
$c.