7

I'm trying to delete all files containing a certain text like this:

$ find ~/Library/MobileDevice/Provisioning\ Profiles/* -exec grep -l "text to search for" '{}' \; -delete
/Users/build/Library/MobileDevice/Provisioning Profiles/06060826-3fb2-4d71-82c6-7b9d309b08d6.mobileprovision
find: -delete: /Users/build/Library/MobileDevice/Provisioning Profiles/06060826-3fb2-4d71-82c6-7b9d309b08d6.mobileprovision: relative path potentially not safe

However, as you can see, it's throwing a warning and then does not delete the file. How can I resolve this error?

This is on a Mac.

6 Answers 6

14

macOS find is based on an older version of FreeBSD find whose -delete would not remove the files that were given as argument.

When you do:

find dir/* ... -delete

Your shell is expanding that dir/* glob into a list of file paths (excluding the hidden ones, while find itself will not exclude the hidden files it finds in any of those dirs), so find receives something like:

find dir/dir1 dir/dir2 dir/file1 dir/file2... ... -delete

If dir/file1 matches macOS find's -delete will refuse to delete it. It will happily delete a dir/dir1/.somefile if it matches though.

That was changed in FreeBSD in 2013, but the change apparently didn't make it to macOS. Here, the work around is easy: use find dir (or find dir/ if you want to allow for dir to be a symlink to a directory and find to descend into it) instead of find dir/*. So, in your case:

find ~/Library/MobileDevice/Provisioning\ Profiles/ \
  -exec grep -l "text to search for" '{}' \; -delete

Or use the more efficient grep -l --null | xargs -0 approach.

1
  • Now works on macOS (bigsur 11.5.2) if you add -mindepth to the call as per another answer. Both dir/* and dir/ same results.
    – vladli
    Oct 26, 2021 at 8:50
8

I ran into this problem on macOS deleting everything except archives from a directory tree:

find top ! -name "*.tar.gz" -print -delete
... snip ...
top
find: -delete: top: relative path potentially not safe

The solution was adding -mindepth 1 to exclude the top directory

find top/path -mindepth 1 ! -name "*.tar.gz" -print -delete
2

Try: find ~/Library/MobileDevice/Provisioning\ Profiles/ -type f -name "name to match" -delete

Edit - first code is not abswer for question, try this: find ~/Library/MobileDevice/Provisioning\ Profiles/ -type f -exec grep -l --null "pattern in file" {} + | xargs -0 rm

9
  • 1
    This is searching for a filename pattern. OP wants to find files which contain a certain string/text.
    – Michael D.
    Jan 30, 2019 at 11:20
  • @MichaelD. Oh, you are right, my bad.
    – Matej
    Jan 30, 2019 at 11:25
  • You can't use xargs in general on the output of find, but especially here, it won't work as the paths of the files contain spaces (all whitespace, quotes backslashes are a problem with find | xargs) Jan 30, 2019 at 12:19
  • 2
    No, I meant -exec grep -q pattern {} \; -print0 | xargs -0 rm. macOS grep should also support GNU's --null option so -exec grep -l --null pattern {} + | xargs -0 rm should also work (and avoid running one grep per file). Jan 30, 2019 at 12:37
  • 1
    Yes. It's correct (there are some race condition issues linked to using xargs rm instead of -delete, but probably not worth working around here as we're presumably not removing files from a directory under control of potentially malicious actors). Jan 30, 2019 at 12:51
0

This is searching for string err in all files in /var/log/ recursive.

I'm not sure if cut, uniq and xargs is available on Mac and this is not using find.

grep -r "err" /var/log/ | cut -d: -f1 | uniq | xargs echo

Replace echo with rm to delete the files.

1
  • 'find', cut, uniq and xargs are standard Unix utilities available on any Unix platform.
    – Kusalananda
    Jan 30, 2019 at 12:13
0

You need to change the star sign (*) in the folder path (right after find) to a dot (.)

i.e., find dir/* ... -delete ==> find dir/. ... -delete

0

For me, this simply worked, using the -name option (find <root_dir> -name <glob_pattern>), instead of using globbing in the root path itself:

find ./tmp -name "*.json" -ctime +60s -type f -delete

thanks to this answer here on this same page for inspiration ;) https://unix.stackexchange.com/a/573178/411724

1
  • oops just realized this isn't exactly what OP is about, but since I had this error for doing the above (using glob for base path) I guess this might help others too.
    – Tchakabam
    May 8, 2021 at 0:30

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .