Remove files without string in name

Using an extended globbing pattern in bash:

rm ./!(*999*)

This requires shopt -s extglob to be enabled (and for safety, also shopt -s failglob, so that no file with the unusual name !(*999*) gets removed by mistake if all filenames contain 999). The pattern !(*999*) will match any name in the current directory, except those names matching *999*. To also remove hidden files (files whose name starts with a dot), also enable the dotglob option.

To only care about regular files or symbolic links to regular files (not directories etc.):

for name in ./!(*999*); do [ -f "$name" ] && rm "$name"; done

The zsh shell equivalent to the above loop would be

rm ./(^(*999*))(.)

Your first command will not work since grep will look inside files. It would remove all files that have lines without 999 in them (had you added the --null option so it works with xargs -0).

Your second command will not work since grep on macOS does not support --null-data (it does however have a --null option, but only for when generating filename output). Also note that it would look for 999 anywhere in the file's path (including directory components), not only the file's name.


Just invert the name condition in find :

find . -type f \! -name "*999*" 

Add -delete or -exec rm {} + to actually remove the matched files.