andi1983
Goto Top

Batch für Ordner und Linkerstellung: Leerzeichenproblem (und Optimierungsmöglichkeiten)

Hallo Zusammen,

bisher war ich auf euren Seiten immer nur lesend aktiv, dieses Mal konnte ich aber leider mit der Boardsuche und auch googlen keine Lösung finden, daher wende ich mich jetzt mit einem Beitrag an euch und hoffe auf Hilfe.

Zu meinem Problem:
Zur Lösung eines Netzlaufwerkthemas in der Arbeit habe ich ein Batchfile geschrieben, welches es den Usern erleichtern soll Ordner auf dem Laufwerk zu erstellen, denn leider ist die vorgegebene Ordnerstruktur etwas kompliziert: (Die Ordner liegen dann natürlich nicht lokal)

ordnerstruktur


Die Ordnerstruktur ist uns bis zur Ebene "Archiv" "E01" - "E60" bzw. "Links" vorgegeben. (Diese werden mit Zugriffsberechtigungen versehen)

Regelmäßig soll nun im nächsten freien Ordner "Exx" ein Unterordner erstellt werden. Wenn dieses Thema dann abgeschlossen ist, wird es ins Archiv verschoben. (Dort benötigt nur noch ein kleiner Nutzerkreis Zugang).
Damit man die Unterordner leichter findet soll sich ein Link zu jedem Unterordner im Ordner "Links" befinden. Selten wird es wohl auch vorkommen, dass in einem Ordner "Exx" mehrere Unterordner vorhanden sind, daher muss also auch das überprüft werden.

Idee war nun also ein Batch welches folgende Funktion erfüllt:
1. Unterordner im nächsten freien Ordner erstellen, Ordner "Links" ablöschen und alle Links neu generieren
bzw.
2. Nur Ordner "Links" ablöschen und alle Links neu generieren ohne einen neuen Ordner zu erstellen (Falls sich eine Name geändert hat o.ä.)


Mit meinem Wissen und entsprechend googlen habe ich nun folgendes Batch "zusammengebastelt":

@ECHO OFF & setlocal
SETLOCAL ENABLEDELAYEDEXPANSION

:Meldung
:REM Abfrage welche Aktion durchgefuehrt werden soll
set /P CHS=["O" fuer Ordner erstellen, "L" fuer Links aktualisieren, [A] fuer Abbruch]?  
CLS
if /I "%CHS%"=="O" goto Ordner  
if /I "%CHS%"=="L" goto Links  
if /I "%CHS%"=="A" goto Abbruch  
goto Meldung

:Ordner
SET /P Ordnernamen1=Bitte Ordnername eingeben...

:REM Suche ein leeres Verzeichnis
set ende=0
for /F %%i in ('dir "d:\test\Ebene2\" /B /Ad') do (  
if !ende! equ 1 goto quit
call :chkdir %%i
)
goto quit

:chkdir
:REM Verzeichnis leer, wenn bei dir-Ausgabe 2 Verzeichnisse
dir "d:\test\Ebene2\%*" | find "2 Verzeichnis(se)" >nul:  
if %errorlevel% equ 0 (
:REM Ordner Links soll, nicht belegt werden. Wenn nur noch dieser gefunden => kein anderer freier Ordner mehr!
if %* equ Links (
echo msgbox"Kein Leeres Verzeichnis mehr vorhanden",vbInformation , "Fehler!!!"> %temp%\msg.vbs   
%Temp%\msg.vbs 
erase %temp%\msg.vbs
set ende=1
goto quit
)
:REM Leerer Ordner gefunden => Erstelle Unterordner dort
echo Erstelle Verzeichnis in:
echo %*
mkdir "d:\test\Ebene2\%*\%Ordnernamen1%"  
set ende=1
)
goto :EOF

:quit
:Links

:REM Erstelle Links zu allen Unterordnern im Ordner Links
del d:\test\Ebene2\links\*.* /q

for /F %%i in ('dir "d:\test\Ebene2\" /B /Ad') do (  
for /F %%j in ('dir "d:\test\Ebene2\%%i\" /B /Ad') do (  
echo "%%j"  
set "linkpath=d:\test\Ebene2\links\%%j__%%i.lnk"  
set "linktarget=d:\test\Ebene2\%%i\%%j"  
set "tmpfile=%temp%\sc.vbs"  
echo set lnk ^= CreateObject^("WScript.Shell"^).CreateShortcut^("!linkpath!"^)>"!tmpfile!"  
echo lnk.TargetPath ^= "!linktarget!" : lnk.Save>>"!tmpfile!"  
cscript //NOLOGO /B "!tmpfile!"  
)
)
:Abbruch


Ein Hauptproblem besteht noch:
Wenn ein Ordnername ein Leerzeichen enthält, dann wird kein gültiger Link erzeugt.

Kann mir hier vielleicht jemand weiterhelfen? Hier konnte ich bisher meinen Fehler leider nicht finden.


Außerdem gehe ich davon aus, dass das Batch an einigen Stellen sicherlich nicht optimal gelöst ist (z.B. das Suchen eines leeren Ordners) oder ich auch irgendwelche Fallstricke nicht bedacht habe, daher wäre ich auch gerne für Verbesserungsvorschläge offen.


Danke und Grüße,
Andi

Content-Key: 535799

Url: https://administrator.de/contentid/535799

Printed on: April 19, 2024 at 15:04 o'clock

Member: Xerebus
Xerebus Jan 16, 2020 updated at 12:15:31 (UTC)
Goto Top
Hallo Andi

habs nur schnell durchgesehen.

ich vermute mal zeile 53 und 54 noch jeweils zwei '

set "linkpath='d:\test\Ebene2\links\%%j__%%i.lnk' "
oder
set linkpath="d:\test\Ebene2\links\%%j__%%i.lnk"
Was sagt hier ein
echo %linkpath%
Member: TK1987
Solution TK1987 Jan 16, 2020 updated at 15:09:13 (UTC)
Goto Top
Muss es denn unbedingt ein Batch+VBS-Script gemurkse sein?

Mit Powershell machst du dir die Sache viel einfacher
$PFAD='C:\Test\Ebene2'  

# Auswahlmenü

	'Was möchten Sie tun?'  
	''  
	' 1  Ordner erstellen'  
	' 2  Links aktualisieren'  
	' 3  Abbrechen'  
	''  
	
	$Choice=Read-host "Auswahl"  

# Auswahl 1 - Ordner erstellen
	if ($Choice -eq '1') {  
		cls
	
		# leeren Ordner finden
			$LeererOrdner=ls -dir $Pfad\* | ? {(ls $_.Fullname).count -eq 0} | select -First 1
			
		# Wenn ein Leerer Ordner existiert, erstelle neuen Ordner dort...
			if ($LeererOrdner){
				"Erstelle Neuen Ordner in '"+$LeererOrdner.FullName+"'"  
				""  
				mkdir ($LeererOrdner.FullName+'\'+(Read-Host "Ordner Name eingeben")) }  
		# ...sonst Fehlermeldung
			else {
				'Kein Leerer Ordner gefunden!'  
				''  
				'Beliebiege Taste zum Beenden... '  
				cmd /c pause >$NULL
				exit
				}
		}

# Auswahl 2 - Links aktualisieren
	if ($Choice -eq '1' -or $Choice -eq '2') {  
		del -Force $PFAD\Links\*
		ls -dir "$PFAD\*\*" | % {  
			$Link=(New-Object -ComObject WScript.Shell).CreateShortcut(("$PFAD\Links\"+$_.Name+'__'+$_.parent+'.lnk'))  
			$Link.TargetPath=$_.FullName
			$Link.Save()
			}
		}
Member: andi1983
andi1983 Jan 16, 2020 at 14:41:36 (UTC)
Goto Top
Hallo Xerebus,

danke für deine Antwort!

Das Problem scheint wohl schon vorher zu sein, denn das

echo "%%j"

in Zeile 52 liefert für den Ordner "mit Leerzeichen" bereits nur noch die Ausgabe "mit"...
Member: andi1983
andi1983 Jan 16, 2020 at 14:47:18 (UTC)
Goto Top
Hallo TK1987,

nein muss es nicht face-smile
Mit Powershell hatte ich nur bisher so gut wie gar nichts am Hut.

Danke dir für deine Mühe das Ganze gleich in PS umzusetzen!!!

Hab es gleich getestet und es funktioniert fast wie gedacht.

Wenn alle "Exx" Ordner belegt sind, es aber noch einen leeren Ordner in tieferer Ebene findet (z.B. \Archiv\Unterordner\weiteres\) dann wird der Ordner in "weiteres" angelegt und nicht die Meldung ausgegeben...

Ansonsten perfekt!

Nochmals herzlichen Dank!
Member: TK1987
TK1987 Jan 16, 2020 at 15:13:10 (UTC)
Goto Top
Zitat von @andi1983:
Wenn alle "Exx" Ordner belegt sind, es aber noch einen leeren Ordner in tieferer Ebene findet (z.B. \Archiv\Unterordner\weiteres\) dann wird der Ordner in "weiteres" angelegt und nicht die Meldung ausgegeben...
Ah ok, dachte das sollte so sein.

Darüber hinaus habe ich gesehen, dass du den Namen des Übergeordneteten Orders im Linknamen auch verwendet hast - das war bei mir auch noch nicht so. Hab die Zeilen 19 & 40 entsprechend oben angepasst.
Member: andi1983
andi1983 Jan 16, 2020 at 19:11:03 (UTC)
Goto Top
Perfekt!

Vielen Dank!!!

Für den Fall einer Falschauswahl habe ich es noch etwas ergänzt:
# Auswahlmenü

	'Was moechten Sie tun?'  
	''  
	' 1  Ordner erstellen'  
	' 2  Links aktualisieren'  
	' 3  Abbrechen'  
	''  

do {
$Choice = Read-Host "Auswahl"  
switch($Choice){
1 {"Ordner erstellen"}  
2 {"Links aktualisieren"}  
3 {"Abbruch!"}  
default {"Ungueltige Eingabe => Neuer Versuch:"}  
}
} while($Choice -ne '1' -and $Choice -ne '2' -and $Choice -ne '3')  
Member: TK1987
TK1987 Jan 16, 2020, updated at Jan 22, 2020 at 22:06:42 (UTC)
Goto Top
Zitat von @andi1983:
Vielen Dank!!!
Aber gerne doch.
Für den Fall einer Falschauswahl habe ich es noch etwas ergänzt [...]
Ich merke, du lernst schnell.
Alternativ dazu, ist es mit Powershell auch möglich, das Ganze als grafische Oberfläche zu basteln.

Ich habe es mal so eingestellt, dass der Button "Ordner erstellen" automatisch deaktiviert ist, wenn kein leerer Ordner gefunden wurde.
$Pfad='C:\Test\Ebene2'  
$LeererOrdner=ls -dir $Pfad | ? {(ls $_.Fullname).count -eq 0} | select -First 1

# Klassen hinzufügen
	Add-Type -AssemblyName System.Windows.Forms
	Add-Type -AssemblyName System.Drawing


# Funktionen für GUI-Elemente
	Function Fenster {
		Param(
			[Alias('t')][string]$Titel,  
			[Alias('r')][int]$Randbreite=15  
			)
		
		$Fenster=New-Object System.Windows.Forms.Form
		$Fenster.Size=New-Object System.Drawing.Size(100,100)
		$Fenster.StartPosition='CenterScreen'  
		$Fenster.AutoSize=$True
		$Fenster.Text=$Titel
		$Fenster.padding=New-Object System.Windows.Forms.Padding($Randbreite)
		
		Return $Fenster
		}
	
	Function Schriftart {
		Param(
			[Alias('a')][string]$Art='Microsoft Sans Serif',  
			[Alias('g')][int]$Größe=11,  
			[Alias('f')][switch]$Fett,  
			[Alias('k')][switch]$Kursiv,  
			[Alias('u')][switch]$Unterstrichen  
			)
		$Stil=[System.Drawing.FontStyle]::Regular
		if ($Fett) {$Stil=[System.Drawing.FontStyle]::Bold}
		if ($Kursiv) {$Stil+=[System.Drawing.FontStyle]::Italic}
		if ($Unterstrichen) {$Stil+=[System.Drawing.FontStyle]::Underline}
		
		$Schrift=New-Object System.Drawing.Font($Art,$Größe,$Stil)
		
		Return $Schrift
		}
	
	Function Button {
		Param(
			[Alias('t')][string]$Text,  
			[int]$x=15,
			[int]$y,
			[Alias('b')][int]$Breite=200,  
			[Alias('h')][int]$Höhe=40,  
			[Alias('s')][object]$Schriftart=(Schriftart)  
			)
			
		$Button=New-Object System.Windows.Forms.Button
		$Button.Text=$Text
		$Button.Location=New-Object System.Drawing.Size($X,$Y)
		$Button.Size=New-Object System.Drawing.Size($Breite,$Höhe)
		$Button.Font=$Schriftart
		
		Return $Button
		}
	
	Function Label {
		Param(
			[Alias('t')][string]$Text,  
			[int]$x=15,
			[int]$y,
			[Alias('b')][int]$Breite=200,  
			[Alias('h')][int]$Höhe=25,  
			[Alias('f')][string]$Farbe,  
			[Alias('s')][object]$Schriftart=(Schriftart)  
			)
			
		$Label=New-Object System.Windows.Forms.Label
		$Label.Text=$Text
		$Label.TextAlign='MiddleLeft'  
		$Label.Location=New-Object System.Drawing.Size($X,$Y)
		$Label.Size=New-Object System.Drawing.Size($Breite,$Höhe)
		$Label.Font=$Schriftart
		$Label.ForeColor=$Farbe
		
		Return $Label
		}
		
	Function Eingabe {
		Param(
			[Alias('t')][string]$Text,  
			[int]$x=15,
			[int]$y,
			[Alias('b')][int]$Breite=280,  
			[Alias('h')][int]$Höhe=25,  
			[Alias('s')][object]$Schriftart=(Schriftart)  
			)
			
		$Eingabe=New-Object System.Windows.Forms.Textbox
		$Eingabe.Text=$Text
		$Eingabe.Location=New-Object System.Drawing.Size($X,$Y)
		$Eingabe.Size=New-Object System.Drawing.Size($Breite,$Höhe)
		$Eingabe.Font=$Schriftart
		
		Return $Eingabe
		}

# Hauptfenster erstellen
	Function Hauptfenster {
		$Hauptfenster=Fenster -t "Auswahl"  
		$Text=Label -t "Was möchten Sie tun?" -y 15 -s (Schriftart -g 12 -f)  
		$ButtonMkdir=Button -t "Ordner erstellen" -y 50  
		$ButtonLinks=Button -t "Links aktualisieren" -y 100  
		$ButtonAbbrechen=Button -t "Abbrechen" -y 150  
	
		# Wenn kein Leerer Ordner existiert, deaktiviere $ButtonMkdir
			if (! $LeererOrdner) {$ButtonMkdir.enabled=$False}
	
		$ButtonMkdir.Add_Click({
			$Hauptfenster.Dispose()
			OrdnerErstellen
			})
		
		$ButtonLinks.Add_Click({
			$Hauptfenster.Dispose()
			LinksAktualisieren
			})
			
		$ButtonAbbrechen.Add_Click({$Hauptfenster.Dispose()})
	
		$Hauptfenster.Controls.Add($Text)
		$Hauptfenster.Controls.Add($ButtonMkdir)
		$Hauptfenster.Controls.Add($ButtonLinks)
		$Hauptfenster.Controls.Add($ButtonAbbrechen)
		
		[void]$Hauptfenster.ShowDialog()
		}

# Fenster Neuen Ordner erstellen
	Function OrdnerErstellen {
		$FensterOrdner=Fenster -t "Neuen Ordner erstellen"  
		$Text=Label -t "Ordner wird erstellt in:" -b 185 -y 15 -s (Schriftart -g 12 -f)  
		$TextPfad=Label -t $LeererOrdner.Fullname -x 200 -y 15 -b 200 -f 'blue' -s (Schriftart -f -u)  
		$FeldText=Label -t "Name eingeben" -y 60 -b 120  
		$FeldEingabe=Eingabe -y 60 -x 135
		
		$ButtonSpeichern=Button -t "Speichern" -x 100 -y 110 -b 100  
		$ButtonAbbrechen=Button -t "Abbrechen" -x 220 -y 110 -b 100  
		
		$ButtonSpeichern.Add_Click({
			mkdir ($LeererOrdner.Fullname+'\'+$FeldEingabe.Text)  
			write-host -n -f yellow "'$($LeererOrdner.Fullname+'\'+$FeldEingabe.Text)'"   
			write-host " wurde erstellt."  
			$FensterOrdner.Dispose()
			LinksAktualisieren
			})

		$ButtonAbbrechen.Add_Click({$FensterOrdner.Dispose()})		

		$FensterOrdner.Controls.Add($Text)
		$FensterOrdner.Controls.Add($TextPfad)
		$FensterOrdner.Controls.Add($FeldText)
		$FensterOrdner.Controls.Add($FeldEingabe)
		$FensterOrdner.Controls.Add($ButtonSpeichern)
		$FensterOrdner.Controls.Add($ButtonAbbrechen)
		
		[void]$FensterOrdner.ShowDialog()
		}

# Links aktualisieren
	Function LinksAktualisieren {
			del -force "$Pfad\Links\*"  
			ls -dir "$PFAD\*\*" | % {  
				$Link=(New-Object -ComObject WScript.Shell).CreateShortcut(("$PFAD\Links\"+$_.Name+'__'+$_.parent+'.lnk'))  
				$Link.TargetPath=$_.FullName
				$Link.Save()
				}
			write-host -n "Links wurden aktualisiert.`n`nBeliebige Taste zum Beenden..."  
			cmd /c pause >$NULL
		}
		
Hauptfenster
Member: andi1983
andi1983 Jan 20, 2020 at 09:51:02 (UTC)
Goto Top
Auch hierfür vielen Dank!
Ich merke, du lernst schnell.
Naja, ich würede mich nicht gerade als großen Programmierer bezeichnen face-wink
Eher als jemanden der mit gewissen Grundkenntnissen dann noch halbwegs google bedienen kann und es sich so zusammenbastelt...

Habe es gerade mal kurz gestartet, er hatte irgendwie beim Ordner erstellen noch ein Problem...
Ansonsten sieht das aber schon mal sehr gut aus face-smile

mkdir : A positional parameter cannot be found that accepts argument
'+\+System.Windows.Forms.TextBox, Text: blubb.Text'.  
At D:\test\Make_dirs_Grafisch.ps1:147 char:4
+             mkdir $LeererOrdner.Fullname+'\'+$FeldEingabe.Text  
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [mkdir], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,mkdir


Hab nur gerade wenig Zeit - ich werds mir in den nächsten Tagen mal näher ansehen woran es scheitert.
Member: TK1987
TK1987 Jan 22, 2020 at 22:08:38 (UTC)
Goto Top
Zitat von @andi1983:
Habe es gerade mal kurz gestartet, er hatte irgendwie beim Ordner erstellen noch ein Problem...
Da hab ich wohl eine Klammer vergessen... Zeile 147 oben angepasst.

Gruß TK1987