Zum Inhalt springen

Script (bash), dass Verzeichnisstrukturen vergleicht und Links anlegt...


van_haakonnen

Empfohlene Beiträge

Hallo Leute,

ich habe mal eine Frage an euch:

Ich habe mir gerade den Advanced Scripting Guide ein bisshen angeguckt aber so wirklich viel weiter hat mich das alles nicht gebracht...

Ich muss ein relativ einfaches Script schreiben (für mich privat). Es geht darum, dass anfangs ein Pfad eingegeben werden kann. z.B. /root/verzeichnis/ und ein weiterer Pfad z.B. /root/verzeichnisNEU/ .

In dem Ausgangspfad liegen weitere Ordner... viele Ordner...

Nun sollen in dem zweiten Pfad in dem Verzeichnis "VerzeichnisNEU" lauter links zu den anderen Ordnern bzw. Dateien angelegt werden.

Es soll also am ende eine Identische Struktur entstehen - nur aus lauter links. Jedoch auch nur in dieser einen Ebene. Also das Script muss nicht in den Ordnern tiefer gehen.

Gleichzeitig soll geprüft werden ob ein Link zu einem Ordner schon angelegt wurde - dieser soll dann um Rechenleistung zu sparen nicht nochmals angelegt werden. Bei gelöschten Ordnern soll auch der Link gelöscht werden.

Ich hoffe ihr könnt mir ein bisschen weiterhelfen oder mit vielleicht eine Idee geben :-)

Das ganze soll ein Shell Script für Linux / Unix sein...

Vielen Dank im Voraus

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hi,

hier hast du einen minimalistischen Einzeiler der deinen Anforderungen entsprechen sollte (Funzt nicht für versteckte (.*) Dateien).


rm /$ZIEL/*;  for foo in $(find /$QUELLE/ -type d -maxdepth 1 | cut -d/ -f$ANZAHL-); do ln -s /$QUELLE/${foo} /$ZIEL/${foo} ;  done

Einfach die Variablen ersetzen. $ANZAHL ist die Zahl der Verzeichnisebenen der Quelle + 1 (/root/dir1/dir2 = -d4-)

Viel spass beim umbauen :)

cu

Link zu diesem Kommentar
Auf anderen Seiten teilen

Moin,

klar, sorry hatte gestern nicht mehr die Zeit dazu, war ja im geschäft nicht daheim :P

Dann hoff ich mal das ich das ganze genau genug erkläre da ich keine Ahnung habe was du schon von Bash alles weisst.

Also ich Zerleg das ganze erstmal in die einzelnen Befehle:

1 Befehl:

rm /$ZIEL/*; 

löscht erstmal die Links im neuen Verzeichnis da es vorkommen kann, dass im Ausgangsverzeichnis etwas gelöscht wird (laut deinen Angaben :) )

2 Befehl:

for foo in

einfache for schleife wobei "foo" die variable mit der Liste der Verzeichnis namen darstellt

$(find /$QUELLE/ -type d -maxdepth 1 | cut -d/ -f$ANZAHL-);

mit diesem Konstrukt wird eine Liste erstellt. Du könntest hier auch die Ordner manuell eintippen aber das soll ja automatisiert ablaufen. die Bash führt also das was innerhalb von $() steht als befehl aus. Der befehl find findet alle Verzeichnisse (-type d) und zwar nur in dieser ebene (-maxdepth 1) dieser lieftert z.b. /dir1/dir2/dir3 zurück . deshalb musst du alles ab dem ersten "/" von hinten her gesehen abschneiden was "cut -d/ -f4-" erledigt. die übergabe der ausgabe von find an cut erfolgt mittels "|". nun hast du eine schöne liste aller Verzeichnisse in der variable $foo

do ln -s /$QUELLE/${foo} /$ZIEL/${foo} ;

hier, innerhalb der schleife, mittels "do" der befehl ls -s ausgeführt was einen ein symlink erzeugt. erstes argument ist eben die quelle und zweites das ziel wo der symlink liegen soll.

done

beendet die for-schleife

sodele, ich hoffe das hilft dir weiter. wenn du noch was speziell erklärt brauchst einfach fragen :) ansonsten gibts ja auch noch die man-pages

cu

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen, vielen Dank! Perfekt erklärt!

Also ich habe vorher noch nicht wirlklich viel im Bereich Bash gemacht...

Aber ich habe auch gerade leider gesehen, dass ich schwachsinn gemacht habe... die Struktur ist leider so falsch...

Ich brauche das andersherum...

wir haben z.B. gegeben:

/Home/Test1/klauspeter

/Home/Test1/henrymühle

"" "" /sabineschmidt

etc...

hier können beliebig viele Nutzer stehen... in einer Ordnerebene.

Jetzt soll aus diesen Usern eien andere Struktur angelegt werden...

Diese Soll dann ähmlich aussehen wir oben. Es soll dann eine Struktur erzeugt werden aus den Namen der Benutzerordner... Immer der erster Buchstabe als Ordner und dann nochmal der zweite - darin dann der Symlink auf den eigentlichen Ordner des Benutzers in Test1

Also:

/Home/Test2/k/l/klauspeter > /Home/Test1/klauspeter

/Home/Test2/h/e/henrymühle > /Home/Test1/henrymühle

/Home/Test2/s/s/sabineschmidt > /Home/Test1/sabineschmidt

Die Namen werden immer kleingeschrieben. So ist es richtig... tschuldige... habe ich erst richtig verstanden als ich gesehen habe, wie das Ergebnis oben in dem Script wirklich aussieht... :rolleyes:

Vielen Dank nochmal!

Link zu diesem Kommentar
Auf anderen Seiten teilen

dann hab ich doch noch fragen:

1. hast du das mit den 2 buchstaben "/s/s/" statts "/s/a/ bei sabine falsch gemacht oder doch richtig und nur falsch erklärt?

2.wozu willst die ersten 2 buchstaben als einzelene ordner im neuen Verzeichnis haben? das macht das gnaze doch einiges komplizierter, wenn das nicht fest vorgegeben ist würde es doch sicher eine einfachere lösung geben...

3.zur info sind das die homeverzeichnise in einer domäne?

cu

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hallo,

natürlich musste das bei "Sabine" "/s/a/" sein. Habe ich mich verguckt als ich es getippt habe...

Genau - das macht es komplizierter... Die bisherige Lösung der Benutzerkonten ist aber leider so in diesem Vor- Nachnamenordnersystem eingeteilt. Die Neue soll einfach direkt mittels dem Benutzernamen funktionieren.

Da aber einige Programme auf den alten Pfad z.B. /Home/Test2/s/a/sabineschmidt eingestellt sind soll man von dort aus per Link automatisch auf das neue Verzeichnis gelangen. Damit man nichts weiter verändern muss...

Nein - das sind keine Homeverzeichnisse in einer Domäne...

Link zu diesem Kommentar
Auf anderen Seiten teilen

also hier mal die theorie:

der befehl solte ja für ein userverzeichnis immernoch funktionieren wenn du noch etwas die pfade (ggf. von hand) anpasst.

Damit das ganze automatisch läuft muss man doch einiges anpassen und wird recht umfangreich. zum einen muss noch eine weitere schleife um die bisherige gebaut werden die dann für jedes userverzeichnis den befehl ausführt. Und noch etwas progammierung wegen der verzeischnisstruktur mit den 2 anfangsbuchtsaben.

Leider fehlt mir dazu immo die zeit auch wenns mich reizen würde das zu bauen. kannst es ja aber selber mal versuchen und ich unterstütz dich soweit es geht :) oben hast du ja schon lösungsansätze... aber erhlich gesagt würde ich sowas lieber in perl proggen ^^

cu

Link zu diesem Kommentar
Auf anderen Seiten teilen

hm... ja...

also theoretisch muss man das doch dann so machen können...

for var1 in $(find /$QUELLE/ -type d | cat -c 3 $ANFANG ...

dann hätte man den ersten Buchstaben... dann das nochmal mit cat -c 4 für den zweiten...

Aber wie baue ich das in die Schleifen ein damit es funktioniert? Ich sah jetzt hier 4 Stunden daran und ich bin zu dooof :confused: :eek

Link zu diesem Kommentar
Auf anderen Seiten teilen

moin erstmal,

nicht ganz, du hast bei cut den delemiter (-d/, das trennzeichen /,) vergessen. und das er von hinten her suchen soll, -c$anzahlderslashes-. dann musst du vom letzen wort die ersten zwei buchstaben zwischenspeichern, was ja wieder min. ein weiterer befehl ist. Sprich du musst dir das wort ind alle buchstaben zerlegen und davon eben die ersten 2 verwenden...

wie gesagt würde dir gerne den code liefern, aber die liebe Zeit. Immer die Kunden mit ihren Serverausfällen :)

cu und viel spass beim basteln

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also soweit ist es...:

---

#!/bin/sh

set -x

echo

echo

echo "SYMLINKS"

echo

#Konfiguration

QUELLE=home/test

ZIEL=home/test2

ANZAHL=4

#Root-Rechte

if [ "$UID" -ne "$ROOT_UID" ]

then

echo "Sie benoetigen Root-Rechte."

exit $E_NOTROOT

fi

#Symlink

rm /$ZIEL/*

for i in $(find /$QUELLE/)

do basename $i | $liste

echo $liste | cut -c3

done

exit 0

---

Aber es funktioniert noch nicht mit dem ersten buchstaben auslesen ... wie bekomme ich das denn hin, dass er den ersten und zweiten wirklich nimmt?

Dann könnte ich ja innerhalb der Schleife per mkdir §ersterbuchstabe und $zweiterbuchstabe die ordner anlegen... vielleicht mit mkdir -p ... aber wie die Syntax da ist habe ich auch noch nicht ganz verstanden....

Link zu diesem Kommentar
Auf anderen Seiten teilen

hmhm... vielen dank. was würde ich ohne dich tun?! :uli

Also ich habe das bis hierhin mal eingebaut... aber ich bekomme einen Fehler den ich nicht verstehe... habe daraufhin die Pfade etwas verändert aber das Ergebnis bleibt das gleiche...

So sieht es jetzt aus:

#!/bin/sh

set -x

echo

echo

echo "SYMLINKS"

echo

#Konfiguration

QUELLE=/home/test

ZIEL=/home/test2

ANZAHL=4

#Root-Rechte

if [ "$UID" -ne "$ROOT_UID" ]

then

echo "Sie benoetigen Root-Rechte."

exit $E_NOTROOT

fi

#Symlink

rm /$ZIEL/*

liste=Tobi >>>> DAS WAR NUR MAL TESTWEISE...

for i in $(find /$QUELLE/)

do

basename $i $liste

echo $liste

for name in $liste

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir $ZIEL/$eins/$zwei

done

done

exit 0

Die Zuweisung in die Variable $liste will irgnedwie noch nicht. Ich erhalte wenn ich die ausgeben lasse gar ncihts... dann habe ich testhalber mal "Tobi" in die Variable geschrieben... damit funktioniert das ordneranlegen an sich... zumindest theoretisch... er zeigt es als erfolgreich an aber wenn ich nachsehe, dann ist da nichts...

Das sind die Ausgaben:

81-2-133-8:/home# ./script-final2.sh

+ echo

+ echo

+ echo SYMLINKS

SYMLINKS

+ echo

+ QUELLE=home/test

+ ZIEL=home/test2

+ ANZAHL=4

+ '[' 0 -ne '' ']'

./script-final2.sh: line 16: [: : integer expression expected

+ rm '/home/test2/*'

rm: cannot remove `/home/test2/*': No such file or directory

+ liste=Tobi

++ find /home/test/

+ basename /home/test/ Tobi

test

+ echo Tobi

Tobi

+ eins=T

+ zwei=o

+ mkdir home/test2/T/o

mkdir: cannot create directory `home/test2/T/o': File exists

Link zu diesem Kommentar
Auf anderen Seiten teilen

hm kann das sein das du $liste nicht um die gefundenen einträge erweiterst sondern überschreibst? Was sich auch immer empfiehlt sind die . und .. im Verz. zu überspringen.

Und die ausgaben beim bearbeiten des zielpfades verwirren mich. einmal ist ein slash davor einmal nicht...

und die buchtsaben evtl in kleine umwandeln falls du das nicht vorausetzten kannst :)

soweit so gut, morgen gehts weiter denn da is nacht rum :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also hier nochmal die Ausgaben des bisherigen Scriptes ohne "set -x":

81-2-133-8:/home# ./script-final2.sh

SYMLINKS

./script-final2.sh: line 18: [: : integer expression expected

rm: cannot remove `/home/test2/*': No such file or directory

test

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

florian

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

fabian

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

sascha

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

andre

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

sabine

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

nina

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

hannes

Tobi

mkdir: cannot create directory `home/test2/T/o': File exists

Ist ja klar - er liest den Namen jetzt richtig aus... schreibt ihn aber irgendwie nicht in die Variable $liste...

Da ich zum Probieren $liste = Tobi gesetzt habe versucht er überall die Ordnerstruktur dafür anzulegen...

aber..trotzallem legt er noch keine Ordner an... also da passiert irgnedwie nichts...

Später im richtigen einsatzgebiet werden alle usernamen klein geschrieben sein...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Also wenn ich es so abändere:

for name in $liste

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir /$ZIEL/$eins

mkdir /$ZIEL/$eins/$zwei

done

Dann legt er die Ordner erfolgreich an ::)

Bleibt jetzt nur noch das Problem mit der Zuweisung in die Variable liste und dann noch das Anlegen der symlinks in dem Verzeichnis... Dann müsste es das doch gewesen sein... juhu

Link zu diesem Kommentar
Auf anderen Seiten teilen

+ mkdir home/test2/T/o

mkdir: cannot create directory `home/test2/T/o': File exists

Du hast das ja auch nicht komplett von t3quill4b0y übernommen, sondern (wahrscheinlich) falsch abgetippelt :D

Denn es muss da noch ein '-p' als Option rein (man mkdir), also kannst du dir den zweiten mkdir sparen...

...

for name in $liste

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir /$ZIEL/$eins

mkdir /$ZIEL/$eins/$zwei

done

mkdir -p /$ZIEL/$eins/$zwei

Link zu diesem Kommentar
Auf anderen Seiten teilen

Jo - danke dir.

Also ich habs jetzt so und das funktioniert auch mit dem Anlegen der Links:

for name in $liste

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir /$ZIEL/$eins

mkdir /$ZIEL/$eins/$zwei

ln -s /$QUELLE/$liste /$ZIEL/$eins/$zwei/$liste

done

Bleibt nur leider immernoch das Problem, dass der der Variablen $liste nicht korrekt die Namen zuweist... :rolleyes:

Ich habe das mit dem mkdir -p /$ZIEL/$eins/$zwei aber so geändert. Das sieht einfach schöner aus :-)

Ansonsten funktioniert es ja jetzt und macht das was es auch machen soll...

Link zu diesem Kommentar
Auf anderen Seiten teilen

Bleibt nur leider immernoch das Problem, dass der der Variablen $liste nicht korrekt die Namen zuweist... :rolleyes:

erklär mir das nochmal (ich glaub ich sitz auf der Leitung *aufsteh und wiederhinsetz* so früh am morgen), ich weiß nicht genau was du meinst.

Am besten postest du nochmal das komplette Skript und erklärst was du haben möchtest..*derweil Kaffee holen geh*

Link zu diesem Kommentar
Auf anderen Seiten teilen

okay :)

Erstmal das Script:

#!/bin/sh

#set -x

clear

echo

echo

echo "SYMLINKS"

echo

#Konfiguration

QUELLE=home/test

ZIEL=home/test2

#Root-Rechte

if [ "$UID" -ne "$ROOT_UID" ]

then

echo "Sie benoetigen Root-Rechte."

exit $E_NOTROOT

fi

#Symlink

rm -R /$ZIEL/*

liste=Tobi

for i in $(find /$QUELLE/)

do

basename $i $liste

echo $liste

for name in $liste

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir -p /$ZIEL/$eins/$zwei

ln -s /$QUELLE/$liste /$ZIEL/$eins/$zwei/$liste

done

done

exit 0

Soooo - jetzt habe ich ja der Variablen "list" einfach mal Tobi zugewiesen... Dann funktioniert das auch. also er legt im ORdner Test2 erst den Ordner T und dann daran das 0 an. Dann den Link zu dem eigenentlichen Ordner.

Das Problem besteht jetzt darin, dass in der Schleife irgnedwie (also hier: basename $i $liste) der Variablen nichts zugewiesen wird. Eigentlich sollte er da ja der Reihe nach die ganzen Namen durchgehen... Das ist bestimmt nur ein Syntaxfehler.....

Link zu diesem Kommentar
Auf anderen Seiten teilen

*beim kaffee holen anschliess*

was schlaubi meint ist bestimmt auch sehr hilfreich: das skript mal posten :)

trotzdem ich glaube $liste ist kein array oder es wird immer wieder überschrieben, und nicht angehängt. Ich hab hier ein kleines Beispiel skript was ein array befüllt und dann ababeitet.


#!/bin/bash


declare -a array

i=0

for foo in a b c d

  do

    array[$i]=$foo

    i=$i+1

done



for a in ${array[@]}

  do echo $a

done


das ganze gibt dann aus:

a

b

c

d

Wenn du das umbaust sollte das problemchen doch gelöst sein?!?!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Hm... nachdem ich mir nun auch einen Kaffee geholt habe bereitet mir das ein kleines verständnisproblem...

Also eigentlicht sollte es doch ausreichen wenn man der der Variablen liste immer nur den aktuellen Namen zuweist... das wird dann abgearbeitet und dann der nächste name in die variable geschrieben... dann wieder abgearbeitet.. oder nicht?

Bzw. wenn ich das mit dem Array mache... an welcher stelle müsste ich das denn einbinden?

Link zu diesem Kommentar
Auf anderen Seiten teilen

Okay habe ich verändert. Es sieht jetzt also so aus:

#!/bin/sh

#set -x

clear

echo

echo

echo "SYMLINKS"

echo

#Konfiguration

QUELLE=home/test

ZIEL=home/test2

#Root-Rechte

if [ "$UID" -ne "$ROOT_UID" ]

then

echo "Sie benoetigen Root-Rechte."

exit $E_NOTROOT

fi

#Symlink

rm -R /$ZIEL/*

foo=0

for i in $(find /$QUELLE/)

do

liste[$foo]=$(basename $i)

foo=$foo+1

done

for name in ${liste[@]}

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir -p /$ZIEL/$eins/$zwei

ln -s /$QUELLE/$liste /$ZIEL/$eins/$zwei/$liste

done

exit 0

Jetzt legt er alle Ordnerstrukturen richtig an. Also er erzeugt den ersten Ordner korret und den darinliegenden auch. Aber als links erstellt er jetzt immer einen Ordner "test"-Link...

////EDIT

Also mit folengem Code legt er auch die Symlinks richtig an:

foo=0

for i in $(find /$QUELLE/)

do

liste[$foo]=$(basename $i)

foo=$foo+1

done

for name in ${liste[@]}

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir -p /$ZIEL/$eins/$zwei

ln -s /$QUELLE/$name /$ZIEL/$eins/$zwei/$name

done

Nur bekomme ich eine Fehlermeldung bei der Ausführung des Scripts:

SYMLINKS

./script-final2.sh: line 18: [: : integer expression expected

rm: cannot remove `/home/test2/*': No such file or directory

ln: `/home/test2/t/e/test/test': File exists

ln: `/home/test2/t/e/test/test': File exists

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dann probiers mal damit:

#!/bin/sh


#set -x


clear


echo

echo

echo "SYMLINKS"

echo


#Konfiguration

QUELLE=home/test

ZIEL=home/test2



#Root-Rechte

if [ "$UID" -ne "[b]0[/b]" ]

then

echo "Sie benoetigen Root-Rechte."

exit $E_NOTROOT

fi



#Symlink

rm -R[b]f[/b] /$ZIEL/*


foo=0

for i in $(find /$QUELLE/)

do

liste[$foo]=$(basename $i)

foo=$foo+1

done


for name in ${liste[@]}

do

eins=${name:0:1}

zwei=${name:1:1}

mkdir -p /$ZIEL/$eins/$zwei

ln -s[b]f[/b] /$QUELLE/$liste /$ZIEL/$eins/$zwei/$liste

done



exit 0


Ich hoffe die fett markierten Stellen kann man sehen (musst genau hinschauen).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Dein Kommentar

Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...