J'ai folderA
qui contient des fichiers avec une séquence numérique commençant par a_000000
. Ce que je veux faire, c'est supprimer les fichiers à partir d'un numéro spécifique: disons a_000750
jusqu'à la fin des fichiers de ce folderA
. Quelqu'un pourrait-il s'il vous plaît indiquer comment faire cela en utilisant un script Shell?
En supposant que vous sachiez ou que vous puissiez deviner la fin de la plage, vous pourriez utiliser expansions d'accolades :
rm a_{000750..000850}
Ce qui précède supprimera les 101 fichiers compris entre a_000750 et a_000850 inclus (et se plaindra des noms de fichiers faisant référence à des fichiers non existants). Si vous avez trop de fichiers pour cela, utilisez find
:
find . -name 'a_*' | while read file; do
[ "${file#./a_}" -gt 000749 ] && rm -v "$file"
done
Ici, find
liste simplement tous les fichiers correspondant à a_*
. La liste est transmise à une boucle while
où chaque nom de fichier est lu dans la variable $file
. Ensuite, en utilisant les fonctionnalités manipulation de chaînes de bash, si la partie numérique (find imprime des fichiers sous la forme ./file
, afin que ${file#./a_}
imprime le nombre uniquement) est égale à 000750
ou plus, le fichier est supprimé. Le -v
est juste là pour que vous puissiez voir quels fichiers ont été supprimés.
Notez que ce qui précède suppose des noms de fichiers sains. Si vos noms peuvent avoir des espaces, des nouvelles lignes ou d'autres caractères étranges, utilisez ceci à la place:
find . -name 'a_*' -print0 | while IFS= read -rd '' file; do
[ "${file#./a_}" -gt 000749 ] && rm -v "$file"
done
Vous pouvez faire quelque chose comme ça:
find . -regextype posix-extended -iregex './a_[0-9]{6}' -execdir bash -c '[[ ${1##./a_} > 000750 ]] && echo $1' "removing: " {} \;
Ou:
find . -regextype posix-extended -iregex './a_[0-9]{6}' | sort | sed '0,/000750/d' | xargs echo
La première méthode suppose un préfixe fixe, le supprime et vérifie la valeur.
La deuxième méthode suppose un suffixe de longueur fixe (et un préfixe fixe commun) et s’appuie sur ce fait; et que, bien que 201
vienne avant 31
dans le lexicographe, il n'en a pas avant 031
.
Testez cela avec la commande echo
et, une fois que vous êtes sûr qu'elle répertorie les fichiers corrects, utilisez plutôt rm
.
la première solution de terdon s'appuie sur le développement d'accolade, qui est une propriété de bash
et ksh
, mais ne peut pas être utilisé dans le shell standard /bin/sh
qui, sur Ubuntu, est lié symboliquement à /bin/dash
.
Dans les cas où vous devez utiliser /bin/sh
pour la portabilité de vos scripts, il existe généralement deux façons de procéder. On serait via globbing. Juste cd folderA
et à partir de là, lancez rm a_*
. L’autre solution consisterait à implémenter une alternative de style C pour une boucle utilisant while <CONDITION>;do ...done
en langage Shell et à formater les nombres avec printf
:
$ sh -c 'i=0;while [ $i -le 750 ]; do filename=$(printf "a_%06d" $i);echo "$filename";i=$((i+1)) ;done'
Notez que j'utilise ici echo
. Remplacez echo "$filename"
par rm ./"$filename"
ou rm -- "$filename"
lorsque vous êtes prêt à supprimer les fichiers. Notez également que cela doit être effectué lorsque vous avez déjà cd
ed dans le répertoire souhaité.
Awk étant un langage similaire à C, peut nous aider de deux manières: (1) nous pouvons générer des noms de fichiers avec une boucle for et les formater via la fonction sprintf
, et (2) supprimer ces fichiers via la commande system()
, qui transmettra notre nom de fichier généré et rm
command to /bin/sh
:
awk 'BEGIN{for(i=0;i<=750;i++){filename=sprintf("a_%06d",i);system("rm "filename);} }'
En continuant avec l'idée d'une approche portable où nous "générons" des noms de fichiers, nous pouvons faire la même chose en Perl:
Perl -le 'for(0..750){$fd=sprintf("a_%06d",$_);unlink($fd)}'