-delete
implies -depth
that doesn't work with -prune
(-depth
starts with the leaves). There's a warning about that in the manual of the GNU version (-delete
is a FreeBSD extension now also supported by GNU find
and a few other implementations).
info -- find -delete
The use of the '-delete' action on the command line automatically
turns on the '-depth' option (*note find Expressions::). This can
be surprising if you were previously just testing with '-print', so
it is usually best to remember to use '-depth' explicitly.
info -- find -prune
Because '-delete' implies '-depth', using '-prune' in combination
with '-delete' may well result in the deletion of more files than
you intended.
Here, you've got the option of either using rm
instead:
find . -name save -prune -o -type f -exec rm -f {} +
(potentially unsafe if there are directory writeable by others in there, as one could make you delete files outside the current directory tree by replacing directories with symlinks while you run that command).
A safer alternative:
find . -name save -prune -o -type f -execdir rm -f -- {} \;
That doesn't have the problem mentioned above but means running one rm
per file. The --
is necessary for the FreeBSD implementation, not the GNU one that prefixes file names with ./
.
Alternatively, as suggested by Costas:
LC_ALL=C find . ! -name save ! -path '*/save/*' -type f -delete
(but that still needlessly descends into save
directories)
The LC_ALL=C
is there so *
matches any sequence of bytes (even those that don't form valid characters in the current locale). Note that it will affect the language of error messages (English instead of the language of the user).
mv save/ ../some/safer/location
prior to such a "generic" delete command (... but of course, prior to your post I'd have done the same check and ran into the same trouble!). Now go find a good "undelete" for the filesystem the files were on ^^