Verzeichnisinhalt auslesen und einzeln verarbeiten

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Benutzeravatar
pangu
Beiträge: 1400
Registriert: 15.11.2011 20:50:52
Lizenz eigener Beiträge: GNU General Public License
Wohnort: /proc/1

Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von pangu » 13.03.2013 18:31:28

Hi Leute,

ich hab ganze alte Profil-Verzeichnisse aus Samba, die in den Jahren von meinen Ex-Kollegen einfach mit chmod 777 versehen wurden, weil sie wohl irgendwo an andren Stellen Zugriffsprobleme bekamen (oder warum auch immer). Ich möchte im Zuge einer Umstrukturierung diese wie folgt abändern und korrigieren. Da ich keine Lust habe jeden einzelnen Ordner zu bearbeiten, möchte ich das mit einem Skript erledigen. Das sollte einfach zu lösen sein, denn den usernamen, den ich für "chown" verwenden möchte, kann ich einfach anhand des Verzeichnisnamens auslesen. Hier wie der Ordner aussieht, alles dadrunter möchte ich verarbeiten:
# ls -l /profiles
[...]
drwxrwxrwx 14 max Domain Users 4096 1.Feb. 2009 max
drwxrwxrwx 13 max grupp2 4096 1.Feb. 2009 max.V2
drwxrwxrwx 12 hans grupxyz 4096 1.Feb. 2005 hans
drwxrwxrwx 15 sibylle Domain Users 4096 1.Feb. 2005 sibylle.V2
drwxrwxrwx 14 foobar kostbar 4096 1.Feb. 2005 foobar
drwxr-x--x 11 moritz looser 4096 2.Feb. 2004 habakuk
[...]
Die Unterordner davon sind wirr-warr, da stimmen die Owner und Gruppen nicht, auch die modes sind ganz verschieden.

Diese Befehle möchte ich anwenden, ich würde also anfangen und folgendes ausführen:

Für den ersten Ordner:

Code: Alles auswählen

chown -R max:'Domain Users' max

Für den zweiten Ordner, ist wieder max sein Ordner, das .V2 ist der Profilordner der für windows7 Maschinen gilt:

Code: Alles auswählen

chown -R max:'Domain Users' max.V2

Für den dritten Ordner:

Code: Alles auswählen

chown -R hans:'Domain Users' hans
usw...

Für die ersten zwei hätte ich ja auch einfach

Code: Alles auswählen

chown -R max:'Domain Users' max*
nutzen können, ich habs aber getrennt aufgelistet, da wir das ja womöglich in einer Art Schleife abarbeiten möchten, so dass es besser ersichtlich wird, was ich tun möchte.

Das letzte Verzeichnis heißt "habakuk" und es gibt jedoch keinen User namens "habakuk". Wenn also der geskriptete "chown xyz..." Befehl einen Fehler ausgibt (errorlevel <> 0), dann heißt das ja dass der User nicht vorhanden war und der chmod nicht angewandt werden konnte. In dem Fall soll einfach aus Sicherheitsgründen dieser Ordner und Unterordner mit "chown -R root. habakuk" versehen werden.

Ganz am Ende möchte ich dann per "chmod" die modes setzen und zwar kann ich das einfach mit diesen zwei Zeilen bewerkstelligen:

Code: Alles auswählen

find /profiles -type d -exec chmod 700 {} +
find /profiles -type d -exec chmod 600 {} +
dadurch werden alle Verzeichnisse nur für den jeweiligen User zugreifbar gemacht, erhalten also read, write, execute. Und für die Dateien möchte ich nur read, write (ohne execute) deswegen 600.

Nun frage ich mich, auch zu Lernzwecken, wie man das so einfach wie möglich (evtl. Einzeiler?) bewerkstelligen könnte. Wie würdet ihr da rangehen? Könnte ich da irgendwie die Variable $(ls) verwenden, muss ich eine Schleife bilden, oder gar mit sed bzw. awk? Ich freue mich auf eure Vorschläge, so kann ich mir Gedanken dazu machen und sehen,wie man das sogar optimieren kann. Sowenig Code wie möglich ist mir am Liebsten (zu Lernzwecken).

Danke an Alle.

EDIT: Mein bisheriges Skript sieht so aus, aber ich bin mir sicher, dass es seeeehr stark verbesserungswürdig ist :)

Code: Alles auswählen

#!/bin/bash
verz=/profiles
for name in $(ls $verz | sed 's/\(.*\)\..*/\1/')
do
if id -u $name >/dev/null 2>&1; then
  chown -R $name:'Domain Users' $name $name.V2 >/dev/null 2>&1
 else
 chown -R root. $name $name.V2 >/dev/null 2>&1
fi
done
find $verz -type d -exec chmod 700 {} \;
find $verz -type f -exec chmod 600 {} \;
Man gibt Geld aus, das man nicht hat, um damit Dinge zu kaufen, die man nicht braucht, um damit Leute zu beeindrucken, die man nicht mag.

Benutzeravatar
Natureshadow
Beiträge: 2157
Registriert: 11.08.2007 22:45:28
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Radevormwald
Kontaktdaten:

Re: AW: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von Natureshadow » 13.03.2013 22:15:18

Code: Alles auswählen

for i in *; do
 chown -R ${i%%.*}:'Domain Users' "$i" || chown -R root:root "$i"
 chmod -R u=rwX,go= "$i"
done
Ungetestet auf dem Handy getippt.

Benutzeravatar
pangu
Beiträge: 1400
Registriert: 15.11.2011 20:50:52
Lizenz eigener Beiträge: GNU General Public License
Wohnort: /proc/1

Re: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von pangu » 14.03.2013 11:58:51

Was bedeutet i%%.* ? Kannst das vielleicht auf die schnelle kurz erläutern? Und wie ist das mit dem || (=oder) gemeint? Tritt das nur ein, wenn der erste Befehl "chown -R $(i%%...usw...)" einen errorlevel ungleich 0 ausspuckt?
Man gibt Geld aus, das man nicht hat, um damit Dinge zu kaufen, die man nicht braucht, um damit Leute zu beeindrucken, die man nicht mag.

Benutzeravatar
Natureshadow
Beiträge: 2157
Registriert: 11.08.2007 22:45:28
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Radevormwald
Kontaktdaten:

Re: AW: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von Natureshadow » 14.03.2013 13:42:44

${foo%%.*} entfernt den longest match vom Ende von foo, der mit . beginnt.

Und ja.

Benutzeravatar
pangu
Beiträge: 1400
Registriert: 15.11.2011 20:50:52
Lizenz eigener Beiträge: GNU General Public License
Wohnort: /proc/1

Re: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von pangu » 14.03.2013 14:39:31

Danke! dieses i%% ist natürlich um einiges komfortabler und kürzer wie meine sed-Zeile zuvor :p Ich verwende jedoch weiterhin die Überprüfung, ob der user tatsächlich auf dem system vorhanden ist, statt dem ||. Der Grund hierfür liegt darin, dass chown auch andere Fehler bringen kann, die jedoch niht auf die Tatsache beruhen, dass es den user nicht gibt. Dann würde einfach root:root gesetzt, das wäre aber falsch. Somit sieht mein Skript aktuell so aus:

Code: Alles auswählen

#!/bin/bash
verz=/data1/profiles
cd $verz
for i in *; do
username=${i%%.*}
if id -u $username >/dev/null 2>&1; then
  chown -R "$username":'Domain Users' "$i"
 else
  chown -R root. "$i"
fi
done
find $verz -type d -exec chmod 700 {} \;
find $verz -type f -exec chmod 600 {} \;
Und das Äquivalente dazu für meine Homeverzeichnisse sieht dann so aus:

Code: Alles auswählen

#!/bin/bash
verz=/data1/homes
cd $verz
for i in *; do
username=${i%%.*}
if id -u $username >/dev/null 2>&1; then
chown -R "$username":root "$i"
else
chown -R root. "$i"
fi
done
find $verz -type d -exec chmod 700 {} \;
find $verz -type f -exec chmod 600 {} \;
Über Verbesserungsvorschläge bin ich natürlich weiterhin dankbar.

EDIT: Mit dem viel geschickteren großen X im chmod Befehl wie von Natureshadow empfohlen (statt find -exec):

Code: Alles auswählen

#!/bin/sh
verz=/data1/profiles
cd $verz
for i in *; do
username=${i%%.*}
  chown -R "$username":'Domain Users' "$i"
 else
  chown -R root. "$i"
fi
done
chmod -R u=rwX,go= $verz
Zuletzt geändert von pangu am 14.03.2013 16:15:28, insgesamt 3-mal geändert.
Man gibt Geld aus, das man nicht hat, um damit Dinge zu kaufen, die man nicht braucht, um damit Leute zu beeindrucken, die man nicht mag.

Benutzeravatar
Natureshadow
Beiträge: 2157
Registriert: 11.08.2007 22:45:28
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Radevormwald
Kontaktdaten:

Re: AW: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von Natureshadow » 14.03.2013 15:44:39

Moin,

benutze niemals bash zum Skripten und niemals find -exec.

Was hat dir an chmod -R u=rwX,go= * nicht gefallen?

Benutzeravatar
pangu
Beiträge: 1400
Registriert: 15.11.2011 20:50:52
Lizenz eigener Beiträge: GNU General Public License
Wohnort: /proc/1

Re: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von pangu » 14.03.2013 16:09:39

Hab ich einfach vergessen zu übernehmen :D chmod ist ja sicherlich auch um einiges schneller wie mein find Befehl, gell?

Bitte erklär mir das auch gleich mit dem "Bash-zum-Skripten-Vermeiden" und "find -exec". Ich schätze mal deswegen, weil bash nicht immer vorhanden ist und aus Gründen der Kompatibilität? Oder aus ganz anderen Gründen? Sollte ich also /bin/sh nutzen in der Shebang?
Man gibt Geld aus, das man nicht hat, um damit Dinge zu kaufen, die man nicht braucht, um damit Leute zu beeindrucken, die man nicht mag.

Benutzeravatar
Natureshadow
Beiträge: 2157
Registriert: 11.08.2007 22:45:28
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Radevormwald
Kontaktdaten:

Re: AW: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von Natureshadow » 14.03.2013 21:01:04

Bash ist lahm und inkompatibel. find -exec hat komische Syntax und ist langsam.

-nik

Benutzeravatar
r900
Beiträge: 1053
Registriert: 09.10.2011 20:06:11
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Stockholm

Re: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von r900 » 14.03.2013 21:24:11

Natureshadow hat geschrieben:find -exec hat komische Syntax und ist langsam.
Das kann ich noch nachvollziehen..
Natureshadow hat geschrieben:Bash ist lahm und inkompatibel
aber jetzt wird's albern. Vieles ist in bash einfacher zu lösen als in sh/dash. Wenn ich z.B. einen string in einer Variablen ersetzen möchte kann ich in bash einfach ${VARIABLE//STRING/ERSETZUNG} benutzen. Nach deiner Aussagen muesste ich sh und sed oder awk oder was auch immer nehmen. Bestimmt nicht schneller als bash.

Also, nicht grundsätzlich bash zu verwenden ist ein guter Hinweis. Aber wenn man seine Gründe hat ist da wohl nichts gegen einzuwenden. Es sei denn man schreibt code der auf möglichst vielen unterschiedlichen Systemen laufen soll.

Benutzeravatar
Natureshadow
Beiträge: 2157
Registriert: 11.08.2007 22:45:28
Lizenz eigener Beiträge: MIT Lizenz
Wohnort: Radevormwald
Kontaktdaten:

Re: AW: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von Natureshadow » 15.03.2013 09:44:43

Häh? Das kann mksh auch…

Bash bricht sogar zwischen minor releases seine eigene Syntax.

Meine Empfehlung ist: Benutze keine Bash. Das ist ja jetzt nicht Gegenstand des Threads, also PN oder neuer Thread bitte.

Benutzeravatar
r900
Beiträge: 1053
Registriert: 09.10.2011 20:06:11
Lizenz eigener Beiträge: GNU Free Documentation License
Wohnort: Stockholm

Re: Verzeichnisinhalt auslesen und einzeln verarbeiten

Beitrag von r900 » 15.03.2013 12:02:46

Natureshadow hat geschrieben:Das kann mksh auch…
Das hat mit dem Thema nun wirklich überhaupt nichts zu tun. Auf Debian-Systemen wird sh im Normalfall durch dash bereitgestellt.
Natureshadow hat geschrieben:Das ist ja jetzt nicht Gegenstand des Threads, also PN oder neuer Thread bitte.
Wenn du so grob verallgemeinerte Dinge von dir gibst musst du schon damit rechnen dass jemand widerspricht. Jetzt hast du deine Meinung kundgetan und ich meine, daher sehe ich keinen Bedarf das in einen neuen Thread ausarten zu lassen.

Antworten