Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

I'm writing a makefile that will clean up some useless files at the end of the compilation. If a target has already been made, it will of course skip that target and the useless file may not be there. So if I do this:

rm lexer.ml interpparse.ml interpparse.mli

I may get errors because one of the files doesn't exist. Is there any way to tell rm to ignore these files?

In reading the man page, I see the following option:

 -f          Attempt to remove the files without prompting for confirma-
             tion, regardless of the file's permissions.  If the file does
             not exist, do not display a diagnostic message or modify the
             exit status to reflect an error.  The -f option overrides any
             previous -i options.

That sounds like almost what I want, but I'm not really sure about the permissions part. Is there a way to do this?

share|improve this question
    
Did you try some rm in a sandbox? It looks like -f does exactly what you want, regardless of the globbing. –  JMD Nov 27 '09 at 17:02
    
If the permissions won't allow it, rm will with the -f option still try to delete it. It will fail. It won't tell you it failed. Useful if the filename is a variable or a glob. –  ultrasawblade Jun 13 '12 at 1:24
add comment

7 Answers

up vote 42 down vote accepted

The -f option is definitely what you want to be using.

The confirmation about file permissions it refers to is this:

$ touch myfile    
$ chmod 400 myfile
$ rm myfile       
rm: remove write-protected regular empty file `myfile'?

So rm will warn you if you try to delete a file you don't have write permissions on. This is allowed if you have write permissions on the directory but is a little weird, which is why rm normally warns you about it.

share|improve this answer
    
Most, but not all systems will ask (I think). Some require -i. –  DaveParillo Nov 27 '09 at 18:11
add comment

If you find some way to glob the file names, rm won't complain if it can't find a match. So something like lexer.m* interpparse.*, etc. should work for you (be careful you're not deleting too much, of course). Also, -f is a perfectly reasonable way to go, as long as you're not hoping that file permissions will save you from deleting a file you didn't want to - if you don't want to delete it, don't put it in the list.

share|improve this answer
    
The globbing would be out of the question as there is a lexer.mll file that I don't want to delete. Thanks for showing why -f is reasonable. I suppose I tend to be overly careful after one too many misguided sudo rm -rf . –  Jason Baker Nov 27 '09 at 16:53
    
Not even a more restrictive lexer.m? ...? That would catch lexer.ml and lexer.mz, but not lexer.mll or lexer.mla. –  JMD Nov 27 '09 at 16:58
    
@JMD: I suppose it depends on your shell and what pattern-matching support it offers for globbing. –  Nick Bastin Nov 29 '09 at 0:56
add comment

I'm way late to the party, but I use this all the time. In a makefile, add - to the beginning of a line to ignore the return value of that line. Like so:

-rm lexer.ml interpparse.ml interpparse.mli
share|improve this answer
add comment

The -f option means that you will not be prompted if something is not as expected. It does not mean that permissions are not taken into account.

If you have not enough privileges to remove a file, it won't be removed.

BUT, if you have enough privileges to change privileges, you file will be removed. This is the case when you are the owner of a file with readonly permissions for owner (-r--------). As owner, you can chmod u+w, then remove it: rm -f will remove that file.

share|improve this answer
add comment

If you don't want to use the -f option, an alternative is:

rm filethatdoesntexist 2> /dev/null 

This will just keep errors from being printed.

share|improve this answer
1  
Unfortunately this will still give an error exit code. –  Shaun McDonald Nov 20 '13 at 17:37
add comment

An alternative:

RmIfIsFile() {  for f in "$@"; do [ -f $f ] && rm $f; done; };  RmIfIsFile lexer.ml interpparse.ml interpparse.mli

Too bad Makefiles can't share shell function definitions across lines.

share|improve this answer
    
Have you tried to use \ (backslash) at the end of a row to let it continue on the next? –  some Jul 31 '12 at 19:35
    
@some: Yes, they can be spread across multiple lines, but to share them across recipes you have to put the definition in a make variable. –  reinierpost Oct 1 '12 at 13:56
add comment

Maybe could help a line similar with:

touch fakefile.exe fakefile.o && rm *.o *.exe

I know that this is not very smart, but it does the job.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.