101

I have a bash script that I want to remove files from various directories. Frequently, they won't be there because they weren't generated and that's fine. Is there a way to get the script not to report that error, but if rm has some other output to report that?

Alternately, is there a better command to use to remove the file that'll be less noisy?

Braiam
  • 35,991
flickerfly
  • 1,651

8 Answers8

158

Use the -f option. It will silently ignore nonexistent files.

From man rm:

   -f, --force
          ignore nonexistent files and arguments, never prompt

[The "never prompt" part means that (a) -f overrides any previously specified -i or -I option, and (b) write-protected files will be deleted without asking.]

Example

Without -f, rm will complain about missing files:

$ rm nonesuch
rm: cannot remove ‘nonesuch’: No such file or directory

With -f, it will be silent:

$ rm -f nonesuch
$
John1024
  • 74,655
  • 6
    Oh, I new that didn't prompt for removal, didn't realize it also ignored nonexistents. I totally skipped over that when looking at man. :-) Thank you. I'll mark this as the answer soon as I'm allowed. – flickerfly Apr 29 '16 at 18:54
13

If your requirement is that rm does not complain about missing files, but that you also want any other output from rm, my suggestion would be to first test for the target file's existence, and only call rm (without the -f flag) if the file actually exists.

# rest of script
# ...
[ -e "$file" ] && rm "$file"
# ...
# rest of script

Calling rm -f on a file that, for example, doesn't have user-write permissions, will remove the file and also not emit the normal prompt for that scenario.

In case you wanted to use the same idea with multiple files, I would create a function definition, like:

qrm() {
  for f
  do
    [ -e "$f" ] && rm "$f"
  done
}

Use it like: qrm file1 file2-does-not-exist *.txt etc here

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
  • 3
    It's worth being aware of the very slight chance of a race condition where the file is deleted (or created) between the test and the removal, but I can't imagine that being relevant in any typical situation where one would be using a shell script. – David Z May 01 '16 at 07:43
  • @DavidZ How could that happen? This tests if something exists and then if that succeeds, removes it so it has to get back a response before the removal starts. – flickerfly Apr 07 '21 at 13:13
9

You stated that you still want to see other output from the rm command when you run it, but using the -f option will suppress those. You will need to filter STDERR for what you want, which is a little tricky, given you want everything else to show.

You will want to use a command like this:

rm -f filename 3>&1 1>&2 2>&3 3>&- | grep -v 'No such file or directory'

Command explained:

  • -f argument is to force through and not prompt for confirmation or errors
  • 3>&1 1>&2 2>&3 3>&- is to switch around STDOUT and STDERR for filtering (you can read more about this here if wanted
  • | grep -v 'No such file or directory' is filtering out the message you do not want to see

Now, if you just wanted to suppress error messages entirely, you could run the following command:

rm filename 2> /dev/null

This command redirects STDERR to /dev/null so you will not see it when you run the command.

muru
  • 72,889
BriGuy
  • 3,211
  • 1
  • 15
  • 20
  • 1
    (AFAICS) rm without -v never outputs to stdout, only stderr, so in this case you could just 2>&1 | grep without the dance which is useful more generally, – dave_thompson_085 Apr 30 '16 at 11:20
5

This is a hack, but you could always touch the file about to be removed. If it doesn't exist, it will be created so rm can remove it.

matega
  • 151
  • 2
  • I like this, except for the performance - how costly is it to touch several K's of files as opposed to only deleting the ones that don't exist? – Dani_l May 01 '16 at 15:12
5

As an alternative, you can use the find command with the -delete option. This will (obviously) only delete the files it finds so it never warns if none are. An example might be:

find /var/log/triffids/ -name "*.log" -mtime 30 -delete

which would search the /var/log/triffids/ directory and delete all files with the .log suffix which have not been modified for more than 30 days.

It is always a good idea to run these commands without the -delete option first, to make sure it's finding the files you expect.

seumasmac
  • 2,015
3

Check the --force (-f) option of rm:

-f, --force

ignore nonexistent files and arguments, never prompt

heemayl
  • 56,300
0

You can use -f as it will, according to the man page:

Attempt to remove the files without prompting for confirmation, 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. also remember The -f option overrides any previous -i options.

rm -f xyz-directory

will not prompt you anything, and will do exactly what you want.

garethTheRed
  • 33,957
-1

There are two main ways: If you add the -f option, it will not show the "doesn't exist" error and two: (works for almost any command) instead of just doing "thecommand" do "thecommand 2>/dev/null" where "thecommand" is the command you're doing.

  • 1
    I was avoiding the piping because I don't want to loose other errors that might come up. I don't know what they would be. – flickerfly Apr 29 '16 at 18:55