J'ai écrit un script qui supprime tout sauf les deux derniers fichiers d'un dossier:
#!/bin/bash
ls -1 --quoting-style=shell-always /path/to/some/folder \
| head -n -2 \
| xargs printf -- "'/path/to/some/folder/%s'\n" \
| xargs sudo rm -rf
Ce script sera exécuté quotidiennement en tant que tâche cron.
Le raisonnement est le suivant:
Obtenir une liste de tous les fichiers en utilisant
ls -1
(pour que j'obtienne un fichier par ligne);Supprimez les deux derniers de la liste en utilisant
head -n -2
;Depuis
ls
imprime des chemins relatifs, utilisez laxargs printf
chose pour ajouter le chemin du dossier et en faire un chemin absolu;Envoyez-les à l'
sudo rm -rf
aidexargs
.
Tout le monde a accès à ce dossier, donc tout le monde peut créer et supprimer tous les fichiers de ce dossier.
Le problème est: sudo rm -rf
est effrayant. xargs sudo rm -rf
est incroyablement effrayant.
Je veux être sûr que personne ne peut endommager d'autres dossiers / systèmes en créant des fichiers intelligents à supprimer (accidentellement ou volontairement). Je ne sais pas, quelque chose d'intelligent comme:
file with / spaces.txt
ce qui pourrait entraîner un super effrayant sudo rm -rf /
.
EDIT: Mon erreur, les noms de fichiers ne peuvent pas contenir /
, donc ce problème spécifique ne se produirait pas, mais la question de savoir s'il existe ou non d'autres risques persiste.
C'est pourquoi j'utilise --quoting-style=shell-always
, cela devrait empêcher toute astuce avec des fichiers avec des espaces. Mais maintenant, je me demande si quelqu'un pourrait être très intelligent avec des espaces et des guillemets dans le nom de fichier, peut-être.
Mon script est-il sûr?
Remarque: j'ai besoin sudo
parce que j'accède au dossier à distance (à partir d'un lecteur réseau mappé à l'aide mount
), et je ne pouvais pas le faire fonctionner sans sudo.
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
?/
on créer un fichier avec le personnage dans le nom J'essaie de réaliser ceci icils
sortie, c'est déjà une commande mal écrite, même avec des guillemets.ls
utilise également les paramètres régionaux pour l'ordre de tri, je pense, donc je ne vois pas à quoi sert lahead
suppression des 2 derniers (sauf si vous essayez de vous débarrasser.
et..
quels iirc ne sont pas autorisés comme arguments derm
toute façon. Utilisez simplementfind /path/to/folder -type f delete
. Et nonsudo
si vous exécutez depuis cron - cron est déjà au niveau racineRéponses:
Sous Linux, tout caractère est un nom de fichier valide constituant un caractère sauf:
\0
(ASCII NUL): utilisé pour la terminaison de chaîne en C/
(barre oblique): utilisé pour la séparation des cheminsAinsi, votre approche ne fonctionnera certainement pas dans de nombreux cas, comme vous pouvez l'imaginer, par exemple, gère-t-elle une nouvelle ligne (
\n
) dans le nom de fichier? ( Indice: non ).Quelques notes:
ls
; utiliser des outils dédiés (il y en a au moins un pour la plupart des cas d'utilisation)xargs
, voyez si vous pouvez vous en sortirfind ... -exec
; dans la plupart des cas, vous serez bien avec justefind
seulJe pense que cela vous permettra de continuer. steeldriver a déjà fourni l'idée séparée par NUL dans le commentaire (
printf -- '%s\0' /path/to/some/folder/* | head -zn -2 | xargs -0 rm
), utilisez-le comme point de départ.la source
find
, merci pour la suggestion.ls
approche d'analyse échouerait. Par exemple, avez-vous pris en compte une nouvelle ligne dans le nom de fichier?head -z
-elle? Cela semble ridicule, mais je n'en ai pasman
niinfo
dans mon conteneur CoreOS linux ... Impossible de trouver sur Internet non plus. Je reçoishead: invalid option 'z'
head
(livré avec GNUcoreutils
). Voici la version en ligne: manpages.ubuntu.com/manpages/xenial/man1/head.1.htmlxargs
prend en charge certains guillemets: avec des guillemets simples, des guillemets doubles ou une barre oblique inverse qui lui permet d'accepter des arguments arbitraires¹, mais avec une syntaxe différente de la syntaxe des guillemets de type Bourne.L'implémentation GNU de
ls
as trouvée sur Ubuntu n'a pas de mode de citation compatible avec lexargs
format d'entrée.Il
ls --quoting-style=shell-always
est compatible avec les shells ksh93, bash et zsh citant la syntaxe, mais uniquement lorsque la sortie dels
est interprétée par le shell dans les mêmes paramètres régionaux quels
lors de sa sortie. De plus, certains paramètres régionaux, comme ceux utilisant BIG5, BIG5-HKSCS, GBK ou GB18030, doivent être évités.Donc, avec ces coquilles, vous pouvez réellement faire:
Mais cela a peu d'avantages sur:
Le seul cas où cela devient utile est lorsque vous souhaitez utiliser l'
-t
option dels
trier les fichiers par mtime / atime / ctime ou-S
/-V
. Mais même alors, vous pourriez aussi bien utiliserzsh
:par exemple pour trier les fichiers par mtime (utiliser
oL
pour-S
etn
pour-V
).Pour supprimer tous les fichiers réguliers, sauf les deux plus récemment modifiés:
¹ il y a encore quelques limitations de longueur (par
execve()
et dans certainesxargs
implémentations non GNU beaucoup plus arbitraires), et certainesxargs
implémentations non GNU obstrueront l'entrée qui contient des séquences d'octets ne formant pas des caractères valides.la source