Der unterstehende Aufruf von rm gibt einen Fehler zurück.
Was teilt mir make, rm mit? Wo ist der Fehler? Was ist zu ändern?
Die eigentliche Funktion - löschen der Dateien - funktioniert.
Bernd schrieb:> Der unterstehende Aufruf von rm gibt einen Fehler zurück.>> Was teilt mir make, rm mit?
Ach es geht um ein Makefile, und nicht um ein Batchfile?
Auf welche Betriebssystem bist du denn unterwegs und wie sieht die
Make-Regel aus?
Bernd schrieb:> Was teilt mir make, rm mit? Wo ist der Fehler? Was ist zu ändern?
Blöde Frage aber:
Macht die bescheuerte Windows-Kommandozeile überhaupt Globbing?
Also Globbing bedeutet, Muster wie "*.png" in eine Liste von passenden
Dateinamen aufzulösen. Das macht z.B. die Bash unter Linux.
Nase schrieb:> Blöde Frage aber:> Macht die bescheuerte Windows-Kommandozeile überhaupt Globbing?
nein zum glück nach, was Linux macht das da bescheuerte;
die bekommt man immer mal bei * das die Komadozeile zu lang ist. Den *
hat die Anwendung zu bearbeiten.
Peter II schrieb:> Nase schrieb:>> Blöde Frage aber:>> Macht die bescheuerte Windows-Kommandozeile überhaupt Globbing?>> nein zum glück nach, was Linux macht das da bescheuerte;>> die bekommt man immer mal bei * das die Komadozeile zu lang ist.
Hab ich noch nie bekommen. Auf meinem System darf die Kommandozeile 2 MB
lang sein. Wenn du soviele Dateien in einem einzelnen Verzeichnis hast,
solltest du eh mal darüber nachdenken, die besser zu organisieren.
Wenn man die GNU-Tools unter Windows benutzt, kommt man aber öfter an
die Grenze, weil dort die Limits viel niedriger sind.
> Den * hat die Anwendung zu bearbeiten.
Sehe ich nicht so.
Für den Fall hier fallen mir mehrere Möglichkeiten ein:
-Der Verzeichnispfad, in dem die Dateien liegen, ist zu lang. Auch diese
Länge ist unter Windows viel zu stark eingeschränkt.
- Der Name einer der Dateien enthält irgendwelche "verbotenen" Zeichen.
- Das Dateisystem hat einen Fehler.
Rolf M. schrieb:> Hab ich noch nie bekommen. Auf meinem System darf die Kommandozeile 2 MB> lang sein. Wenn du soviele Dateien in einem einzelnen Verzeichnis hast,> solltest du eh mal darüber nachdenken, die besser zu organisieren.
ist schon nach jeden Tag aufgeteilt. Noch mal aufteilen macht keinen
sinn mehr.
da kann man nicht mal rm *.log machen ohne einen Fehler zu bekommen. Da
muss man sich die finger mit find *.log --exec rm {} \; (oder so)
brechen.
Aus dem Grund finde ich die Windows-Lösung hier besser.
Peter II schrieb:> Aus dem Grund finde ich die Windows-Lösung hier besser.
Das Problem bei der Windows-Lösung ist nur, dass jede Anwendung ihre
teils sehr eigenen Vorstellungen davon hat, welche Arten von Globbing
wie zu interpretieren sind und ob überhaupt. Genau wie der Wildwuchs
voneinander inkompatibler und/oder unvollständiger oder nicht
vorhandenet Möglichkeiten, Anführungszeichen etc. zu escapen. Schon
blöd, wenn man ein etabliertes Escapezeichen als Pfadtrenner verwendet
und dann dessen Funktion nicht gleichwertig ersetzt.
Peter II schrieb:> da kann man nicht mal rm *.log machen ohne einen Fehler zu bekommen. Da> muss man sich die finger mit find *.log --exec rm {} \; (oder so)> brechen.
Klingt stark nach Windows ->
https://support.microsoft.com/en-us/kb/830473
Summary
This article discusses the limitation to the length of the strings that
you use from the command prompt in Command Prompt (Cmd.exe) and the
methods that you can use to work around this limitation.
More information
On computers running Microsoft Windows XP or later, the maximum length
of the string that you can use at the command prompt is 8191 characters.
On computers running Microsoft Windows 2000 or Windows NT 4.0, the
maximum length of the string that you can use at the command prompt is
2047 characters.
This limitation applies to the command line, individual environment
variables (such as the PATH variable) that are inherited by other
processes, and all environment variable expansions. If you use Command
Prompt to run batch files, this limitation also applies to batch file
processing.
Examples
The following list gives you some examples of how this limitation
applies to commands that you run in Command Prompt and commands that you
use in a batch file.
In Command Prompt, the total length of the following command line
that you use at the command prompt cannot contain more than either 2047
or 8191 characters (as appropriate to your operating system):
cmd.exe /k ExecutableFile.exe parameter1, parameter2 ... parameterN
In a batch file, the total length of the following command line that
you use in the batch file cannot contain more than either 2047 or 8191
characters (as appropriate to your operating system):
cmd.exe /k ExecutableFile.exe parameter1, parameter2 ... parameterN
This limitation applies to command lines that are contained in batch
files when you use Command Prompt to run the batch file.
In Command Prompt, the total length of EnvironmentVariable1 after
you expand EnvironmentVariable2 and EnvironmentVariable3 cannot contain
more than either 2047 or 8191 characters (as appropriate to your
operating system):
c:> set
EnvironmentVariable1=EnvironmentVariable2EnvironmentVariable3
In a batch file, the total length of the following command line
after you expand the environment variables in the command line cannot
contain more than either 2047 or 8191 characters (as appropriate to your
operating system):
ExecutableFile.exe parameter1parameter2
Even though the Win32 limitation for environment variables is 32,767
characters, Command Prompt ignores any environment variables that are
inherited from the parent process and are longer than its own
limitations of either 2047 or 8191 characters (as appropriate to the
operating system). For more information about the SetEnvironmentVariable
function, visit the following Microsoft Web site:
http://msdn2.microsoft.com/en-us/library/ms686206.aspx
How to work around the limitation
To work around the limitation, use one or more of the following methods
(as appropriate to your situation):
Modify programs that require long command lines so that they use a
file that contains the parameter information, and then include the name
of the file in the command line.
For example, instead of using the ExecutableFile.exe Parameter1
Parameter2 ...ParameterN command line in a batch file, modify the
program to use a command line that is similar to the following command
line, where ParameterFile is a file that contains the required
parameters (parameter1 parameter2 ...ParameterN):
ExecutableFile.exe c:\temp\ParameterFile.txt
Modify programs that use large environment variables so that the
environment variables contain less than either 2047 or 8191 characters
(as appropriate to your operating system).
For example, if the PATH environment variable contains more than
either 2047 or 8191 characters (as appropriate to your operating
system), use one or more of the following methods to reduce the number
of characters:
Use shorter names for folders and files.
Reduce the depth of folder trees.
Store files in fewer folders so that fewer folders are required
in the PATH environment variable.
Investigate possible methods that you can use to reduce the
dependency of PATH for locating .dll files.
Fenster schrieb:> Peter II schrieb:>>> da kann man nicht mal rm *.log machen ohne einen Fehler zu bekommen. Da>> muss man sich die finger mit find *.log --exec rm {} \; (oder so)>> brechen.>> Klingt stark nach Windows ->> https://support.microsoft.com/en-us/kb/830473
nein, das ist ein Linux Problem wenn man viele Dateien in einem
Verzeichnis hat. Bei Windows tritt diesen Problem nicht auf, weil dem rm
der * einfach übergeben wird.
Peter II schrieb:> Rolf M. schrieb:>> Hab ich noch nie bekommen. Auf meinem System darf die Kommandozeile 2 MB>> lang sein. Wenn du soviele Dateien in einem einzelnen Verzeichnis hast,>> solltest du eh mal darüber nachdenken, die besser zu organisieren.>> ist schon nach jeden Tag aufgeteilt. Noch mal aufteilen macht keinen> sinn mehr.>> da kann man nicht mal rm *.log machen ohne einen Fehler zu bekommen. Da> muss man sich die finger mit find *.log --exec rm {} \; (oder so)> brechen.
Du hast ernsthaft jeden Tag soviele Log-Files, daß deren Namen zusammen
länger als 2 MB sind? Wie geht denn das? Wenn jedes Logfile einen 20
Zeichen langen Namen hat, wären das 100.000 Logfiles pro Verzeichnis und
über einen kompletten Tag verteilt im Schnitt mehr als ein Logfile pro
Sekunde. Irgendwas stimmt doch da nicht.
Rolf M. schrieb:> Du hast ernsthaft jeden Tag soviele Log-Files, daß deren Namen zusammen> länger als 2 MB sind? Wie geht denn das? Wenn jedes Logfile einen 20> Zeichen langen Namen hat, wären das 100.000 Logfiles pro Verzeichnis und> über einen kompletten Tag verteilt im Schnitt mehr als ein Logfile pro> Sekunde. Irgendwas stimmt doch da nicht.
mit den log war nur ein Beispiel. Ja wie haben täglich mehr als 20.000
Dateien in einem Verzeichnis. Die Dateinamen sind etwas länger.
Bernd schrieb:> Die eigentliche Funktion - löschen der Dateien - funktioniert.
Na dann ist es doch o.k.
Unter Windows kannst Du statt rm das ERASE oder DEL-Kommando nehmen.
Dirk schrieb:> Peter II schrieb:>>> find *.log --exec rm {} \;>> Besser find . -name '*.log' -print0 | xargs -0 rm>> Bei Bedarf noch ein -maxdepth dazu
es geht sogar einfach, find hat direkt eine Option zum löschen, vergesse
aber jedesmal wie der Parameter ist.
Dirk schrieb:> Peter II schrieb:>>> find *.log --exec rm {} \;>> Besser find . -name '*.log' -print0 | xargs -0 rm>> Bei Bedarf noch ein -maxdepth dazu
Nein. Besser find -name '*.log' -exec rm {} +
Mit dem + wird rm auch für mehrere Treffer aufgerufen und spart die
Pipe.
Dirk schrieb:> Peter II schrieb:>>> find *.log --exec rm {} \;>> Besser find . -name '*.log' -print0 | xargs -0 rm>> Bei Bedarf noch ein -maxdepth dazu
Du hast aber schon mitbekommen, daß es gerade darum geht, nicht alle
Dateien einem einzigen rm-Aufruf zu übergeben?
Rolf M. schrieb:> Du hast aber schon mitbekommen, daß es gerade darum geht, nicht alle> Dateien einem einzigen rm-Aufruf zu übergeben?
Beide Varianten - -exec ... + oder mit xargs - verteilen die Argumente
so, dass die Kommandozeile nicht zu lang wird, ohne dadurch auf das
Zusammenfassen zu wenigen Aufrufen zu verzichten.
Malte S. schrieb:> Rolf M. schrieb:>> Du hast aber schon mitbekommen, daß es gerade darum geht, nicht alle>> Dateien einem einzigen rm-Aufruf zu übergeben?>> Beide Varianten - -exec ... + oder mit xargs - verteilen die Argumente> so, dass die Kommandozeile nicht zu lang wird, ohne dadurch auf das> Zusammenfassen zu wenigen Aufrufen zu verzichten.
Ok, das war mir nicht bewußt.
Planlos schrieb:> Peter II schrieb:>> find hat direkt eine Option zum löschen,>> find . -name *.log -delete
So hast du aber den entscheidenden Teil, nämlich das Auswerten von *.log
durch die Shell gerade nicht vermieden.
Rolf M. schrieb:>> find . -name *.log -delete>> So hast du aber den entscheidenden Teil, nämlich das Auswerten von *.log> durch die Shell gerade nicht vermieden.
richtig ist es glaube ich so
find . -name "*.log" -delete
Peter II schrieb:> richtig ist es glaube ich so>> find . -name "*.log" -delete
Besser wäre wie schon in vorherigen Beispielen gezeigt '*.log' statt
"*.log". Letzteres wertet z.B. immer noch Umgebungsvariablen aus. Wenn
also irgendwo mal in einem Dateinamen ein $ vorkommt, funktioniert das
nicht mehr richtig.
Rolf M. schrieb:> Besser wäre wie schon in vorherigen Beispielen gezeigt '*.log' statt> "*.log". Letzteres wertet z.B. immer noch Umgebungsvariablen aus. Wenn> also irgendwo mal in einem Dateinamen ein $ vorkommt, funktioniert das> nicht mehr richtig.
das verstehe ich jetzt nicht.
wenn find der Parameter "*.log" übergeben wird, steht dann ohne " in
argv drin. Was hat das mit den gefundenen Dateien zu tun?
Rolf M. schrieb:> Besser wäre wie schon in vorherigen Beispielen gezeigt '*.log' statt> "*.log". Letzteres wertet z.B. immer noch Umgebungsvariablen aus. Wenn> also irgendwo mal in einem Dateinamen ein $ vorkommt, funktioniert das> nicht mehr richtig.
Nein. Nur wenn in "*.log" ein $ vorkäme, wäre das der Fall. Die
expandierte Form von *.log wird nicht erneut auf Variablen etc.
ausgewertet.
Dennoch ist ' generell besser, wenn nicht ausdrücklich Expansion
gewünscht ist.
Wenn es nur um ein einzelnes * geht, tut's natürlich auch \*.log
Peter II schrieb:> Rolf M. schrieb:>> Besser wäre wie schon in vorherigen Beispielen gezeigt '*.log' statt>> "*.log". Letzteres wertet z.B. immer noch Umgebungsvariablen aus. Wenn>> also irgendwo mal in einem Dateinamen ein $ vorkommt, funktioniert das>> nicht mehr richtig.>> das verstehe ich jetzt nicht.>> wenn find der Parameter "*.log" übergeben wird, steht dann ohne " in> argv drin. Was hat das mit den gefundenen Dateien zu tun?
Stimmt schon. Ich nutze aus dem oben genannten Grund aus Gewohnheit
immer '', wenn ich nicht explizit will, daß Umgebungsvariablen
ausgewertet werden. Hier ist das aber an sich kein Problem.
Bernd schrieb:> "make clean" wird aus einer Batchdatei aufgerufen.> clean:> rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak> rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)
Witzig, da steht nix von wegen Log-Dateien.
Was wenn man rm die zu löschenden Dateine in kleinere "Häppchen"
füttert?
Um mal auf das eigentliche Problem zurückzukommen (die Diskussion
war ja völlig in eine andere Richtung gegangen):
Bernd schrieb:> Was teilt mir make, rm mit? Wo ist der Fehler?
In der Windows-Version von (GNU) rm, welches du wohl hier aufrufst.
> Was ist zu ändern?
rm wäre zu reparieren. :-)
Es sollte nie "invalid argument" produzieren, sondern bestenfalls
"no such file or directory", wobei letzteres bei Option -f zu
ignorieren ist (damit würde dein "make" fortsetzen).
Die Bourne-Shell übergibt übrigens auch auf Unixen tatsächlich
*.eps etc., wenn keine Datei auf das Muster passt, aber da das
rm unter Unix dann in der Tat "no such file or directory" liefert,
geht's bei rm -f eben weiter.
Der Würgaround in unseren Makefiles (so sie sowohl auf Windows als
auch Unix/Linux lauffähig sein sollen) ist es, jeweils eine solche
Datei vorher anzulegen:
rm: Aufruf von lstat für "*.eps" nicht möglich: Invalid argument
9
rm: Aufruf von lstat für "*.png" nicht möglich: Invalid argument
10
rm: Aufruf von lstat für "*.pdf" nicht möglich: Invalid argument
11
rm: Aufruf von lstat für "*.bak" nicht möglich: Invalid argument
12
make: *** [clean] Fehler 1
Damit hat das rm dann was, was es wirklich immer löschen kann, und
es geht weiter.
Alternativ kannst du vor die rm-Aufrufe im Makefile ein Minuszeichen
schreiben. Damit bekommst du zwar immer noch eine Fehlermeldung,
aber "make" macht dennoch weiter.
Jörg W. schrieb:> Damit hat das rm dann was, was es wirklich immer löschen kann, und> es geht weiter.
Unter Windows beschwert sich DEL auch, wenn es nichts zu löschen findet.
Dagegen hilft dann ein Guard:
Peter D. schrieb:> Dafür gibt es auch Lösungen:
Die ich allerdings allesamt noch krückiger finde als „unsere“ Variante,
jeweils eine Dummy-Datei vorher anzulegen.
Aber wie schon geschrieben: der eigentliche Bug ist (meiner Meinung
nach) in GNU rm selbst. „rm -f irgendwas“ heißt „lösche ‚irgendwas‘,
sofern es existiert, ohne weitere Rückfrage, halt' aber die Klappe,
wenn es nicht existiert“.
Jörg W. schrieb:> Die ich allerdings allesamt noch krückiger finde als „unsere“ Variante,> jeweils eine Dummy-Datei vorher anzulegen.
Die mit dem test Kommando scheint mir recht brauchbar zu sein.
Peter D. schrieb:> Jörg W. schrieb:> Die ich allerdings allesamt noch krückiger finde als „unsere“ Variante,> jeweils eine Dummy-Datei vorher anzulegen.>> Die mit dem test Kommando scheint mir recht brauchbar zu sein.
Geht nicht, wenn das make mit cmd.exe statt einer Unix-Shell
arbeitet. Been there, done that.
echo hi > dummy.file
geht in beiden Shells.
Jörg W. schrieb:> Geht nicht, wenn das make mit cmd.exe statt einer Unix-Shell> arbeitet.
D.h. die /utils/bin/test.exe gibt es unter Windows nur bei GCC
Compilern?
Peter D. schrieb:> Jörg W. schrieb:> Geht nicht, wenn das make mit cmd.exe statt einer Unix-Shell> arbeitet.>> D.h. die /utils/bin/test.exe gibt es unter Windows nur bei GCC> Compilern?
Mit dem GCC selbst hat das nicht direkt was zu tun, irgendwer muss
halt die entsprechenden Unix-Kommandos überhaupt installiert
haben (so wie auch das rm.exe).
Altes WinAVR, Atmel Toolchain älterer Version und aktuelle Version
sind da leider alle leicht unterschiedlich, was sie genau mitbringen.
Das ist aber gar nicht so entscheidend, denn die entsprechende
if-Anweisung gehört zur Unix-Shell (die mit dem "fi" hintendran).