cinda
Goto Top

Dateien im verzeichnis und dessen unterverzeichnis mit DEL löschen

Hallo zusammen, ich wende mich an euch, weil ich nicht weiter komme, vielleicht kann mir jemend helfen.Hier ist mein problem:
[Edit Biber]...na ja, "problem" ist etwas übertrieben...nennen wir es "Anforderung" *smile* Geschlossen 24.2.2006 [/Edit]

Das programm soll mir mit xcopy aktuelle dateien von einem verzeichnis auf dem anderen kopieren, und überprüfen, wenn eine datei im verzeichnis B existiert und nicht im verzeichnis A, dann soll diese datei gelöscht werden. Stimmt die syntax im code ??
Besten Dank im voraus!

rem @echo off

set A=@"C\bilder\unterverzeichnis_n"
set B=@"D\bilder"\unterverzeichnis_n

XCOPY A\* B\ /E /Y /I /D

ECHO Löschen der dateien,die nur in B existieren und nicht in A

FOR /D %%d IN (B\*) DO (
FOR %%f IN (%%d\*) DO (
IF NOT EXIST A\%%f (
DEL %%d\%%f /P
) ELSE (
echo Datei '%%d\%%f' existiert nicht!
)
)
)
rem pause

Content-ID: 26191

Url: https://administrator.de/forum/dateien-im-verzeichnis-und-dessen-unterverzeichnis-mit-del-loeschen-26191.html

Ausgedruckt am: 23.12.2024 um 13:12 Uhr

hudson
hudson 16.02.2006 um 17:19:36 Uhr
Goto Top
gib mal "del /?" in der cmd ein...

also ich mache es immer mit del /s /q

/s steht für alle dateien in allen unterverzeichnissen
/q steht für keine rückfrage...
cinda
cinda 17.02.2006 um 10:06:21 Uhr
Goto Top
Hallo,

ich habe es probiert, aber ich kriege es leider nicht hin. Eine ausführliche antwort wird mir helfen, da ich nicht viels von batch kenne face-smile
hudson
hudson 17.02.2006 um 10:24:31 Uhr
Goto Top
also probier mal dein batchfile wie folgt umzuschreiben:

rem @echo off

set A=@"C\bilder\unterverzeichnis_n"
set B=@"D\bilder"\unterverzeichnis_n

XCOPY A\* B\ /E /Y /I /D

ECHO Löschen der dateien,die nur in B existieren und nicht in A

FOR /D %%d IN (B\*) DO (
FOR %%f IN (%%d\*) DO (
IF NOT EXIST A\%%f (
DEL %%d\%%f /P /S /Q
) ELSE (
echo Datei '%%d\%%f' existiert nicht!
)
)
)
rem pause


habs selbst nicht getestet.... fällt mir nur spontan ein...
habe nur DEL %%d\%%f /P /S /Q hinzugefügt.

versuchs doch mal obs jetzt klappt.


gruß hudson
Biber
Biber 19.02.2006 um 14:10:52 Uhr
Goto Top
Moin cinda,

ich würde Dir zwei andere Ansätze empfehlen für Dein Vorhaben.

a) Schau Dir bitte das Robocopy.exe-Utilitily von M$ an. Ich mag es zwar nicht, aber es gibt dort einen Schalter /MIR wie "Mirror", der zwei Verzeichnisse in Deinem Sinne synchron hält, also im Zielverzeichnis auch Dateien löscht, die im Quellverzeichnis nicht (mehr) vorhanden sind.

b) Wenn Du den Ehrgeiz hast, dieses mit XCopy nachzubilden, ist es IMHO das Übersichtlichste, VORÜBERGEHEND für den Batch das Quell- und das Zielverzeichnis zu einem "virtuellen" Laufwerk zu machen.
Das hat auch den Vorteil, dass Du die paar Restzeilen problemlos am CMD-Prompt durchspielen kannst.
Beispiel (im Batch):
::------XCopyMIRROR.bat
subst q: C:\Windows\temp
subst z: %temp%\unterverzeichnis_neu
:: Q: wie Quelle und Z: wie Ziel...
XCOPY q:\*.* z:\*.* /s /E /Y /I /D
ECHO Löschen der dateien,die nur in B existieren und nicht in A
FOR /F %%i IN ('dir /s /b Z:\*.*') DO IF NOT Exist q:%%~pnxi Del Z:%%~pnxi
Subst q: /d
Subst z: /d
::-----snapp XCopyMIRROR.bat

That's all.

Gruß Biber

P.S. Für den SET-Befehl und das Ansprechen von Variablen schau bitte noch mal in die Hilfe zu SET /? oder FOR /? oder in eines der Tutorials im Bereich "Batch & Shell".
set A=@"C\bilder\unterverzeichnis_n"
set B=@"D\bilder"\unterverzeichnis_n
XCOPY A\* B\ /E /Y /I /D
Richtiger:
set "A=C:\bilder\unterverzeichnis_n"
set "B=D:\bilder\unterverzeichnis_n
XCOPY %A%\*.* %B% /E /Y /I /D
cinda
cinda 20.02.2006 um 10:25:56 Uhr
Goto Top
Hallo,

danke für die antwort. Mit Xcopy funktionniert das. Problem ist immer noch mit DEL vorhanden. Wenn ich deinen Tipp richtig verstehe, dann soll ich zwei virtuelle verzeichnisse erstellen q und z. Ich versthe hier aber nicht das zusammenhang mit meinen verzeichnissen A und B. Wo soll ich sie deklarieren?

Gruß
Cinda
Biber
Biber 20.02.2006 um 10:45:45 Uhr
Goto Top
Moin cinda,

sorry, habe ein schlechtes Beispiel gewählt.
Bitte ersetze in meinem Batchschnipsel dei subst-Zeilen so:
Subst q: [Laufwerk:\]C\bilder\unterverzeichnis_n
subst Z: [Laufwerk:\]\D\bilder"\unterverzeichnis_n

-bzw-
Subst q: C:\bilder\unterverzeichnis_n
subst Z: D:\bilder"\unterverzeichnis_n
... falls mit "C" und "D" Laufwerksbuchstaben gemeint waren.

Der Rest kann so bleiben.
Gruß Biber
cinda
cinda 20.02.2006 um 15:26:27 Uhr
Goto Top
Hallo zusammen,

ich habe versucht mit dem folgenden Batch, die dateien, die nur in C existieren und nicht in D, zu löschen, aber es geht nicht. Nach dem ausführen sind die dateien immer noch vorhanden!!! Ich weiß nicht, wie ich das problem lösen kann face-sad

Subst q: C:\bilder\unterverzeichnis_n
subst Z: D:\bilder"\unterverzeichnis_n


ECHO Löschen der dateien,die nur in C existieren und nicht in D

FOR /F %%i IN ('dir /s /b Q:\*.*') DO IF NOT Exist Z:%%~pnxi Del Q:%%~pnxi /q > C:/temp/Backup/backup3.log

Subst q: /d
Subst z: /d

rem pause
cinda
cinda 20.02.2006 um 15:33:43 Uhr
Goto Top
er legt die beiden virtuellen Verzeichnissen aber er löscht die dateien nicht! Hab ich was vergessen??

Grüße
Cinda
Biber
Biber 20.02.2006 um 15:44:51 Uhr
Goto Top
Sorry, cinda,
übersehener Tippfehler von mir: ein Anführungszeichen zuviel....

FALSCH:
subst Z: D:\bilder"\unterverzeichnis_n

RICHTIGER:
subst Z: D:\bilder\unterverzeichnis_n

Pardon.
Biber
cinda
cinda 20.02.2006 um 15:51:16 Uhr
Goto Top
leider kein ergebnis, die dateien sind nicht gelöscht!!
Frage: im virtuellen verzeichnissen soll mir die entsprechenden dateien löschen, richtig?
Wenn ja, dann macht er leider nicht

Gruß
Cinda
Biber
Biber 20.02.2006 um 16:20:18 Uhr
Goto Top
Tja, cinda,
bei mir tut er das..
Wenn Du Deine oben geposteten Zeile so laufen lässt ( ohne "echo off" am Anfang) müsste doch doch bei Dir die "aufgelöste FOR-Zeile stehen. Was steht denn drin?
Und was steht in der ....*.Log-Datei?

Ist ja nur noch eine relativ kurze Zeile, die einen Tippfehler enthalten kann, das sollten wir rausfinden.. *gg

Gruß
Biber
cinda
cinda 20.02.2006 um 17:23:28 Uhr
Goto Top
hey Biber,
dieses mal habe einfach den batch so gegeben, wie du es mir gesagt hast. Ist das richtig?
Wenn das programm läuft, dann werden die dateien im virtuellen verzeichnis Q gelöscht oder ??

Subst q: C:\bilder\unterverzeichnis_n
Subst Z: D:\bilder"\unterverzeichnis_n
:: Q: wie Quelle und Z: wie Ziel...

ECHO Löschen der dateien,die nur in q existieren und nicht in z
FOR /F %%i IN ('dir /s /b Q:\*.*') DO IF NOT Exist z:%%~pnxi Del Q:%%~pnxi

Subst q: /d
Subst z: /d
::-----snapp XCopyMIRROR.bat

Viel Grüße
cinda

PS: wofür steht: ~pnxi
Biber
Biber 20.02.2006 um 17:57:22 Uhr
Goto Top
Hmm, cinda,
beim zweiten "subst" ist Dir wieder dieses Anführungszeichen reingerutscht.

Bitte füge zur Sicherheit nach den beiden Subst-Zeilen ein;
subst
pause

...bevor Du Batch wieder startest. Wenn dann NICHT angezeigt wird:
Q:\: => C:\bilder\unterverzeichnis_n
Z:\: => D:\bilder\unterverzeichnis_n

...dann kannst Du den Batch mit Control-C (auf Oldenburger Platt auch Strg-C genannt) abbrechen. Die beiden ge-Subst-eten Laufwerke müssen schon da sein, sonst geht es nicht.

Der Rest wird deutlich, wenn a) die Substlaufwerke da sind und b) Du den Batch OHNE einleitendes "Echo off" laufen lässt.
Dann werden die etwas kryptischen Platzhalter wie z:\%%~dpni aufgelöst.
Eine detaillierte Beschreibung findest Du in der hilfe zum FOR-Befehl (FOR /? am CMD-Prompt).
Ganz verkürzte Kurzfassung
In der Klammer der ersten FOR..IN..DO-Anweisung werden über den DIR-Befehl einzelne "vollständige Dateinamen" herausgegeben als Variable %%i
%%i ---> Q:\bilder\unterverzeichnis_n\subdir23\beispiel4.txt

Aus diesem "vollständigen Dateinamen" kann ich teile wie Laufwerk (="~d" wie drive), Pfad (="~p" wie path), Name (="~n" wie name) und Endung (="~x" wie eXtension) einzeln oder in Kombination aus- oder abwählen.
Also:
%%~di ---> Q:\ -----------> nur den laufewerksbuchstaben des "ganzen" Elements %%i
%%pi ---> \bilder\unterverzeichnis_n\subdir23 ------> nur den Pfad von %%i
%%pnxi ---> \bilder\unterverzeichnis_n\subdir23\beispiel4.txt
--->Pfad, Name und Endung des Elementes %%i

...und dieses (jetzt gar nicht mehr so kryptische) %%pnxi vergleich ich auf Laufwerk Q wie Quell und Z: wie Ziel.
Bei meinem Durchlauf kam so etwas raus:

...
IF NOT Exist q:\Dbvisu\db2java.zip Del z:\Dbvisu\db2java.zip
IF NOT Exist q:\Dbvisu\db2jcc.jar Del z:\Dbvisu\db2jcc.jar
...
... als mein/Dein/unser Bätschelchen hier lief (OHNE "echo off").

Bin leider kein so guter Erklärer, aber Du rufst ja gottseidank nicht über eine 0190er Nummer an.

Grüße Biber
[Edit] P.S.
A propos "erklären":
Derartige Fragen darfst Du in zukunft auch ruhig im Bereich "Batch & Shell" stellen, wenn Du magst... da gibt es viel nettere Mods als hier unter "Windows" face-wink
[/Edit]
cinda
cinda 21.02.2006 um 09:53:45 Uhr
Goto Top
Hallo Biber,

danke für deine ausführliche Erklärung. Also es geschieht folgendes bei mir:

Beim ausführen der batch datei, werden zwei quellen mit rotem Fragezeichnis in explorer angezeigt. Aber ich kann sie nicht öffnen. Im cmd steht am ende "Drücken Sie eine beliebige taste (wegen subst pause)". Nach dem drücken dieser taste, versuche ich wieder, die quellen zu öffnen, aber es geht nicht. Was mache ich falsh ? Wie sieht die reinfolge aus, damit ich zugriff auf die beiden quellen bekomme? wird den DEL befehl in diesen quellen ausgeführt?

Viel Grüße
Cinda
cinda
cinda 21.02.2006 um 11:25:41 Uhr
Goto Top
Hey Biber,

ich bin es nochmal. Es sieht besser aus. Es wird in cmd-prompt gezeigt, wie das programm die verzeichnisse vergleicht. Am ende zeigt mir "Drücken sie eine beliebige taste".Heißt das er ist fertig? Direkt danach habe ich nachgeschaut, ob die dateien gelöscht wurden oder nicht, aber sie sind leider noch da. Muß ich noch warten?? Wann ist das programm komplett fertig ist??

Viel Grüße
Cinda
Ovis
Ovis 21.02.2006 um 12:30:30 Uhr
Goto Top
Hallo Cinda,

ich hänge mich da einfach mal rein in die Diskussion. Also bei mir hat das Bätchelchen von Biber funktioniert, er löscht das, was nicht in Z: vorhanden ist, aus Q: heraus.
Damit habe ich gespielt.

set "q=C:\temp2\test\txt1"
set "z=C:\temp2\test\txt2"

Subst q: %q%
Subst Z: %z%
:: Q: wie Quelle und Z: wie Ziel...

ECHO Löschen der dateien,die nur in q existieren und nicht in z
FOR /F %%i IN ('dir /s /b Q:\*.txt') DO IF NOT Exist z:%%~pnxi Del Q:%%~pnxi

Subst q: /d
Subst z: /d

Ich würde damit erstmal ausprobieren, ob´s überhaupt funktioniert. Vielleicht hat sich bei dir der Schreibteufel eingenistet. Danach kannst du es, wenn´s funktioniert zu deiner Wunschbatch umbauen.

grüsse ovis

ps: bin kein batchprofi ...
cinda
cinda 21.02.2006 um 12:44:59 Uhr
Goto Top
Hallo ovis,

danke für den tipp. Hier ist mein code, vielleicht übersehe ich den fehler:

::------backup.bat

Subst q: C:\bilder\unterverzeichnis_n
Subst z: D:\bilder\unterverzeichnis_n

:: Q: wie Quelle und Z: wie Ziel...

ECHO Löschen der dateien,die nur in q existieren und nicht in z
FOR /F %%i IN ('dir /s /b Q:\*.*') DO IF NOT Exist z:%%~pnxi Del Q:%%~pnxi

Subst q: /d
Subst z: /d

Subst
Pause

::-----snapp backup.bat
Ovis
Ovis 21.02.2006 um 14:15:10 Uhr
Goto Top
hmmm, also bei mir macht auch dein Code was er soll.
Was macht er denn nicht?
Lass dir doch mal rausschreiben, was er löscht, vielleicht siehst du dann etwas.
FOR /F %%i IN ('dir /s /b Q:\*.*') DO IF NOT Exist z:%%~pnxi Del Q:%%~pnxi /s /q >> c:\cinda.log

grüsse
ovis
Biber
Biber 21.02.2006 um 19:49:34 Uhr
Goto Top
Also, cinda,
auf die Gefahr hin, dass ich mich wiederhole, aber magst Du nicht mal Deinen Batch OHNE "echo off" am Anfang starten? Dann müsste doch irgendetwas auf dem bildschirm zu sehen sein, oder?

@Ovis
Die Parameter /s /q hinter dem DEL-Befehl sind lieb gemeint, aber in diesem Fall
- ist /q überflüssig (es werden ja nicht mehrere Dateien mit Platzhaltern "*" oder "?" gelöscht
- ist /s sogar schädlich... wenn er die Dateien in den Unterverzeichnissen löscht... von denen wissen wir doch gar nicht, ob sie zu löschen sind *gg

Gruß Biber
cinda
cinda 21.02.2006 um 20:53:28 Uhr
Goto Top
Hey biber,

ich habe die ganze zeit mein programm ohne "echo off" gestartet face-smile
Auf dem CMD-Prompt tut sich was. Die schleife durchläuft und alles läuft wunderbar.Nur am ende werden die dateien nicht gelöscht. Ich weiß es nicht warum!

Viel Grüße

PS: Ovis, danke für den hinweis!
Biber
Biber 22.02.2006 um 09:22:13 Uhr
Goto Top
Moin cinda,

tja, sind eventuell diese Dateien ReadOnly gesetzt, so dass die sich nicht löschen lassen? Kommt denn eine Meldung wie "Datei nicht gefunden" oder "Zugriff verweigert"?

Etwas am Rumraten
Biber
cinda
cinda 22.02.2006 um 15:13:23 Uhr
Goto Top
Hallo biber,

danke für alles! Ich habe den Xcopy batch datei in c# programm eingebunden. Das klappt wunderbar. Ich habe noch einen wunsch, ich möchte die zeit beim kopieren messen. d.h. wie lange das dauert (in second beispiel), bia alle daten kopiert sind. Geht das?

Viel Grüße
Cinda
Biber
Biber 22.02.2006 um 18:40:10 Uhr
Goto Top
Moin cinda,
ich habe noch einen Wunsch...
Wer hat denn bloß dieses Gerücht mit den drei freien Wünschen hier im Forum freigesetzt? face-wink

Aber, na gut, weil es nicht so lange dauert:

- entweder über das Tool "timeThis.exe" aus dem M$-ResKit (siehe dann mit TimeThis /?)
- oder mit Bibers Bordmitteln

a) Im Batch VOR der Arbeit die Sekunden beim Start merken in der Variablen %SecsStart%

for /F "tokens=1-3 delims=:,." %%i in ("%time%") do Set /a "SecsStart=%%i*3600+ %%j*60+%%k"
> da kommt dann z.B 56789 heraus...
b) Im Batch NACH der Arbeit die XCopy und DEL-Mimik die Sekunden beim Ende merken in %SecsEnde%

for /F "tokens=1-3 delims=:,." %%i in ("%time%") do Set /a "SecsEnde=%%i*3600+ %%j*60+%%k"
> da kommt dann z.B 57000 heraus...

c) Differenz berechnen und Anzeigen/wegschreiben:
Set /a "SecsVerbraten=%SecsEnde%-%SecsStart%"
:: -------> da kommt dann also 57000-56789 heraus..wieviel das auch immer sein mag...
Echo Der Batch hat gebraucht: %SecsVerbraten%
Echo Ende des Batch am %date% um %time%...
REM ......( oder: Echo Der Batch hat gebraucht: %SecsVerbraten% >>logfile.log )

Schönen Abend
Biber

P.S. Bei der nächsten "Ach, übrigens, da fällt mir ein"-Frage bitte einen neuen Thread aufmachen und diesen hier vorher schließen... face-wink
cinda
cinda 22.02.2006 um 22:38:45 Uhr
Goto Top
Hallo Biber,

danke für deine Großzügigkeit face-smile

dann soll meine batch-datei so aussehen:

::------backup.bat

set "A=C:\bilder\unterverzeichnis_n"
set "B=D:\bilder\unterverzeichnis_n

for /F "tokens=1-3 delims=:,." %%i in ("%time%") do Set /a "SecsStart=%%i*3600+ %%j*60+%%k"

XCOPY %A%\*.* %B% /E /Y /I /D

for /F "tokens=1-3 delims=:,." %%i in ("%time%") do Set /a "SecsEnde=%%i*3600+ %%j*60+%%k"

Set /a "SecsVerbraten=%SecsEnde%-%SecsStart%"

Echo Der Batch hat gebraucht: %SecsVerbraten%
Echo Ende des Batch am %date% um %time%...
REM ......( oder: Echo Der Batch hat gebraucht: %SecsVerbraten% >>logfile.log )

::------backup.bat

Wobei bei den letzten Zeilen kann ich eine möglichkeit auswählen.
Biber
Biber 22.02.2006 um 23:04:13 Uhr
Goto Top
Jepp, cinda,
so sollte es passen...
Ich wollte aber nicht großzügig oder gönnerhaft rüberkommen.. so war es nicht gemeint..
..aber heute abend hat Werder Bremen gespielt.. da wollte ich diesen Thread mal schnell zu Ende bekommen.
Werder hat 3:2 gewonnen.. jetzt darfst Du mich wieder alles fragen, was Dir einfällt...

Grün-weiße Grüße
Frank / der Biber aus Bremen (der Stadt des deutschen Meisters 2006)
cinda
cinda 22.02.2006 um 23:13:30 Uhr
Goto Top
Hallo Bibier!

Hat sie schon gegen gegen Juventus gespielt?! Meine Gratulation . Hoffentlich kann sie doch noch auf die Qualifikation für das Champions-League-Viertelfinale hoffen.
Cool, dann gehen zur nächste frage face-smile

Wie ich sehe, ist die Zeit in second gemessen oder? Kannst du schnell das programm erklären. Was bedeutet SecsVerbraten


Viel Grüße
Cinda
Biber
Biber 23.02.2006 um 00:02:39 Uhr
Goto Top
Na, cinda,
da ist nicht so viel zu erklären...
Ich nehme die Zeit laut Umgebungvaribale %time% VOR dem XCopy/Del-Geraffel.
Die kommt in der Form "12:01:05,23" oder ähnlich.
Die rechne ich um in Sekunden... 12*3600+01*60+05*=43200+60+5 = 43265
Dasselbe NACH XCopy/Del ....Ergebnis meinetwegen 43500.
Die Differenz 43500 minus 43265 gleich 235sec sind meine verbratenen Sekunden.

Soweit die Skizze... wenn der Batch vor Mitternacht anfangen könnte und nach Mitternacht enden kann, müsste man/frau den natürlich anpassen.

Und da M$ einen Bug kultiviert beim Rechnen mit den Werten "08" und "09", müsste im Prinzip auch die SET-Formel geändert werden auf
...Set /a "SecsStart=(1%%i-100)*3600+(1%%j-100)*60+(1%%k-100)"

...aber es sollte ja nur eine Skizze sein...

Den Bug habe ich beschrieben im Batch-TutIII im Bereich "Batch & Shell", schau da mal rein.
Würde mich wirklich freuen, wenn wir diesen Thread hier endlich als "Gelöst" erklären könnten.. wir kommen sonst hier von Ästlein auf Zweiglein...

Grüße
Biber
cinda
cinda 23.02.2006 um 08:39:13 Uhr
Goto Top
Danke Biber,

ok geht klaro face-smile

Merci beaucoup
Viel Grüße
Cinda
Biber
Biber 23.02.2006 um 09:09:34 Uhr
Goto Top
War mir ein Vergnügen, cinda,

ich habe den Beitrag auch schon auf "gelöst" gesetzt - wenn noch Fragen offen sind, weißt Du ja, wo Du mich findest.
Wenn ich nicht grad im Weserstadion bin... face-wink

Bis zum nächsten Batch
Biber
cinda
cinda 23.02.2006 um 10:41:38 Uhr
Goto Top
yao,

damit wir das thema definitiv schließen, habe ich gerade die zeit beim kopieren gemessen und er zeigte: SecsVerbraten = 35320. Wenn ich richtig verstanden habe, dann sind das in sekunden, dann sind das 588,66 in minuten und 9,81 in stunden!!
Das kann nicht wahr sein.Das kopieren hat ungefähr 20mn gedauert!

PS: er hat auch ein fehler gezeigt, wegen der komma in millisekunden (..., 55,15)

Bruß
Cinda
Biber
Biber 23.02.2006 um 10:57:48 Uhr
Goto Top
Moin cinda,

schön, mal wieder von Dir zu lesen... *gg

Ändere bitte die SETs nach den FOR...("%time%")..DO-Anweisungen in:
..Set /a "SecsStart=(1%%i-100)*3600+(1%%j-100)*60+(1%%k-100)" ...bzw.
..Set /a "SecsEnde=(1%%i-100)*3600+(1%%j-100)*60+(1%%k-100)"

Der Beginn der FOR-Anweisung sollte, wie oben beschrieben, jeweils sein:
for /F "tokens=1-3 delims=:,." %%i in ("%time%") do ...

Dadurch sollte der Millisekunden-Teil der Zeit ("10:40:23,22") abgeschnitten werden. Lass Dir sicherheitshalber ausgeben:
Echo SecsStart: [%SecsStart%]
Echo SecsEnde: [%SecsEnde%]
...nachdem Du sie gesetzt hast.

Das bekommen wir schon hin, und wenn das bis zur nächsten Werder-Meisterschaftsfeier dauert...
Gruß bzw. Bruß zurück
Biber