Agora você está dando um loop pelas palavras-chave ( for arg in.. ) e, em seguida, para cada palavra-chave, verificando quais arquivos contêm essa palavra-chave ( grep -l $arg * ).
Para verificar se há arquivos com todas as palavras-chave que você poderia inverter e executar o loop em todos os arquivos ( for f in * ), execute loop pelas palavras-chave ( for arg in "$@" ), verificando se o arquivo as contém ( grep -qe "$arg" "$f" ) somente removendo se todos eles corresponderem.
Isso é uma força bruta, já que você executaria grep n * m vezes, para arquivos n e < em> m palavras-chave. A alternativa seria executar grep -l para a primeira palavra-chave e, em seguida, grep -l para a segunda palavra-chave, dando grep à lista de arquivos retornados pelo último grep etc. Você provavelmente desejaria salvar a lista de arquivos em uma matriz em cada etapa.
Como observação, isso não faz sentido:
for args in "$@"; do
if [ $# != 0 ];
Você está verificando os argumentos numéricos dentro de um loop que é executado uma vez para cada argumento. $# é zero exatamente quando não há argumentos, mas "$@" também não contém nada e o loop não será executado.
Aqui:
grep -l $args * | while read theFile;
Você provavelmente deve citar $args e talvez queira dar uma olhada em BashFAQ 001 para obter informações sobre usando while read ...
Em suma, você provavelmente quer
grep -l "$args" * | while IFS= read -r theFile; do