Forum: Compiler & IDEs Batchdatei: Aufruf von rm produziert Fehler


von Bernd (Gast)


Lesenswert?

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.
1
C:\Users\Host\Desktop\AVR-Projekte\Fahrrad>make clean
2
rm -rf *.o fahrrad.elf *.eps *.png *.pdf *.bak
3
rm: Aufruf von lstat für "*.eps" nicht möglich: Invalid argument
4
rm: Aufruf von lstat für "*.png" nicht möglich: Invalid argument
5
rm: Aufruf von lstat für "*.pdf" nicht möglich: Invalid argument
6
rm: Aufruf von lstat für "*.bak" nicht möglich: Invalid argument
7
make: *** [clean] Fehler 1

von Rolf M. (rmagnus)


Lesenswert?

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?

von Bernd (Gast)


Lesenswert?

Windows 8.1

"make clean" wird aus einer Batchdatei aufgerufen.
1
clean:
2
  rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak 
3
  rm -rf *.lst *.map $(EXTRA_CLEAN_FILES)

von Nase (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

Info:

make und rm gehören zur GCC-Toolchain für Windows. Sollte also 
funktionieren.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Malte S. (maltest)


Lesenswert?

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.

von Fenster (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

Zu blöd um die Frage zu verstehen?

von Dirk (Gast)


Lesenswert?

Peter II schrieb:

> find *.log --exec rm {} \;

Besser find . -name '*.log' -print0 | xargs -0 rm

Bei Bedarf noch ein -maxdepth dazu

von Peter II (Gast)


Lesenswert?

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.

von Malte S. (maltest)


Lesenswert?

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.

von Rolf M. (rmagnus)


Lesenswert?

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?

von Malte S. (maltest)


Lesenswert?

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.

von Planlos (Gast)


Lesenswert?

Peter II schrieb:
> find hat direkt eine Option zum löschen,

find . -name *.log -delete

von Rolf M. (rmagnus)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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?

von Malte S. (maltest)


Lesenswert?

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

von Rolf M. (rmagnus)


Lesenswert?

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.

von beric (Gast)


Lesenswert?

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?
1
EXTS := eps png pdf bak lst map
2
clean:
3
  rm -rf *.o $(PRG).elf
4
  for ext in $(EXTS); do rm -rf *.$ext ; done
5
  rm -rf $(EXTRA_CLEAN_FILES)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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:
1
C:\Users\Host\Desktop\AVR-Projekte\Fahrrad>make clean
2
echo hi > foo.o
3
echo hi > foo.eps
4
echo hi > foo.png
5
echo hi > foo.pdf
6
echo hi > foo.bak
7
rm -rf *.o fahrrad.elf *.eps *.png *.pdf *.bak
8
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.

von Peter D. (peda)


Lesenswert?

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:
1
if exist *.tmp del *.tmp

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Peter D. schrieb:
> Dagegen hilft dann ein Guard:

Entegen der Überschrift ging's hier aber um ein Makefile, nicht um
ein Batchfile.

von Peter D. (peda)


Lesenswert?

Jörg W. schrieb:
> Entegen der Überschrift ging's hier aber um ein Makefile

Dafür gibt es auch Lösungen:

http://stackoverflow.com/questions/5553352/how-do-i-check-if-file-exists-in-makefile

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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“.

von Peter D. (peda)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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).

: Bearbeitet durch Moderator
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.