Supprimer les files par expression régulière

Je veux conserver les files dont les noms correspondent à [0-9A-Z]{1,2}_\d{4}_\w+?\.dat A1_2001_pm23aD.dat , par exemple, A1_2001_pm23aD.dat , K_1998_12.dat et supprimer le rest.

Cependant, les commands ls et rm ne prennent pas en charge de telles expressions rationnelles. Comment puis-je faire ceci?

Utilisation de globs étendus:

 shopt -s extglob printf '%s\n' !([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat) 

ceci va imprimer tous les noms de files / directorys qui ne correspondent pas à [[:digit:][:upper:]] suivi de zéro ou d'un [[:digit:][:upper:]] [[:digit:]] entre _ s puis un ou plusieurs [[:alnum:]] avant l'extension .dat .
Si vous souhaitez effectuer une search récursive:

 shopt -s globstar shopt -s extglob printf '%s\n' **/!([[:digit:][:upper:]]?([[:digit:][:upper:]])_[[:digit:]][[:digit:]][[:digit:]][[:digit:]]_+([[:alnum:]]).dat) 

Alternativement, avec gnu find (vous pouvez utiliser une regex):

 find . -regextype egrep ! -regex '.*/[[:digit:][:upper:]]{1,2}_[[:digit:]]{4}_[[:alnum:]]+\.dat$' 

Il y a plusieurs façons de le faire. Vous pouvez utiliser un langage de script qui comprend les expressions régulières. Par exemple, dans Perl:

 perl -le 'unlink(grep(!/[0-9A-Z]{1,2}_\d{4}_\w+?.dat/,@ARGV))' * 

Cela searchra tous les files ( pas les sous-directorys ) dans le directory courant, collectera ceux qui ne correspondent pas à l'expression rationnelle et les supprimera.

Vous pouvez également faire une chose similaire avec bash, il vous suffit de traduire la regex en POSIX ERE:

 for f in *; do [[ "$f" =~ [0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat ]] || rm "$f"; done 

Notez que dans votre regex, \w+?.dat essayera de faire correspondre la plus petite string alphanumérique possible à tout caractère et dat . Je ne vois pas pourquoi tu voudrais utiliser +? ici et vous avez probablement voulu utiliser \.dat . Je suppose que vous voulez probablement aussi vérifier que le nom de file entier correspond, de sorte que des choses comme foobarfoobarfoobarA1_2001_pm23aD.datfoobarfooabr sont également supprimées. Si c'est le cas, utilisez l'un d'entre eux à la place:

 perl -le 'unlink(grep(!/^[0-9A-Z]{1,2}_\d{4}_\w+\.dat$/,@ARGV))' * 

ou

 for f in *; do [[ "$f" =~ ^[0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat$ ]] || rm "$f"; done 

Enfin, pour supprimer également les directorys, vous pourriez faire:

 for f in *; do [[ "$f" =~ ^[0-9A-Z]{1,2}_[0-9]{4}_[a-zA-Z0-9]+.dat$ ]] || rm -rf "$f"; done 

Vous pouvez le faire avec find :

 find . -regextype posix-extended \ -type f ! -regex '.*/[0-9A-Z]{1,2}_[[:digit:]]{4}_[[:alnum:]_]+?\.dat' -delete 
  • Bien sûr, vous pouvez tout mettre sur une seule ligne (en supprimant le \ à la fin de la première ligne).
  • -regextype posix-egrep semble fonctionner aussi bien que -regextype posix-extended .
  • Si votre version de find ne supporte pas -delete , utilisez -exec rm -- {} + ou -exec rm -- {} ';' .
  • Si vous souhaitez searchr uniquement le directory de niveau supérieur, utilisez -maxdepth 1 .