35 votes

Est-ce que ls listera toujours les fichiers que rm supprimera?

Quelque chose que je sens que je devrais savoir avec certitude : si je ls , rm supprimera-t-il exactement les mêmes fichiers que ls a affichés ? Y a-t-il des circonstances où rm pourrait supprimer des fichiers que ls n'a pas montrés ? (Ceci est dans le bash 18.04)

Éditer: merci à tous ceux qui ont répondu. Je pense que la réponse complète est une combinaison de toutes les réponses, donc j'ai accepté la réponse la plus votée comme "la réponse".

Des choses inattendues que j'ai apprises en cours de route :

  • ls n'est pas aussi simple que vous pourriez le penser dans le traitement de ses arguments
  • Dans une installation non modifiée d'Ubuntu, .bashrc alias ls
  • Ne nommez pas vos fichiers en commençant par un tiret car ils peuvent ressembler à des arguments de commande, et en nommant un -r vous le demandez !

41voto

Daniele Santi Points 2916

Eh bien, à la fois ls et rm fonctionnent sur les arguments qui leur sont passés.

Ces arguments peuvent être un simple fichier, donc ls fichier.ext et rm fichier.ext fonctionnent sur le même fichier et le résultat est clair (afficher le fichier / supprimer le fichier).

Si par contre l'argument est un répertoire, ls répertoire liste le contenu du répertoire tandis que rm répertoire ne fonctionnera pas tel quel (c'est-à-dire que rm sans drapeaux ne peut pas supprimer les répertoires, alors que si vous faites rm -r répertoire, il supprime de manière récursive tous les fichiers sous répertoire et le répertoire lui-même).

Mais gardez à l'esprit que les arguments de la ligne de commande peuvent être soumis à l'expansion du shell, donc il n'est pas toujours garanti que les mêmes arguments soient transmis aux deux commandes s'ils contiennent des jokers, des variables, la sortie d'autres commandes, etc.

À titre d'exemple extrême, pensez à ls $(rand).txt et rm $(rand).txt, les arguments sont "les mêmes" mais les résultats sont bien différents!

21voto

ilkkachu Points 1499

Si vous pensez à quelque chose comme ls foo*.txt vs. rm foo*.txt, alors oui, ils afficheront et supprimeront les mêmes fichiers. Le shell étend le glob, et le passe à la commande en question, et les commandes agissent sur les fichiers répertoriés. L'une les répertoriant, l'autre les supprimant.

La différence évidente est que si l'un de ces fichiers était un répertoire, alors ls afficherait son contenu, mais rm échouerait à le supprimer. Ce n'est généralement pas un problème, car rm supprimerait moins que ce qui était affiché par ls.

Le gros problème ici vient de l'exécution de ls * ou rm * dans un répertoire contenant des noms de fichiers commençant par un tiret. Ils se développeraient en lignes de commandes des deux programmes comme si vous les aviez écrits vous-même, et ls prendrait -r pour signifier "ordre de tri inverse", tandis que rm prendrait -r pour signifier une suppression récursive. La différence importe si vous avez des sous-répertoires d'au moins deux niveaux de profondeur. (ls * affichera le contenu des répertoires du premier niveau, mais rm -r * supprimera tout ce qui se trouve au-delà du premier sous-niveau aussi.)

Pour éviter cela, écrivez des globs permissifs avec un ./ initial pour indiquer le répertoire actuel, et/ou mettez un -- pour signaler la fin du traitement des options avant le glob (c'est-à-dire rm ./* ou rm -- *).

Avec un glob comme *.txt, ce n'est en fait pas un problème car le point est un caractère d'option invalide, et provoquera une erreur (jusqu'à ce que quelqu'un développe les utilitaires pour inventer un sens pour cela), mais il est toujours plus sûr de mettre le ./ de toute façon.


Bien sûr, vous pourriez également obtenir des résultats différents pour les deux commandes si vous modifiez les options de globbing du shell, ou créez/déplacez/supprimez des fichiers entre les commandes, mais je doute que vous ayez voulu parler de ces cas. (Traiter les nouveaux/fichiers déplacés serait extrêmement compliqué à faire en toute sécurité.)

18voto

Sergiy Kolodyazhnyy Points 97292

En laissant de côté le comportement de la coquille, concentrons-nous uniquement sur ce que les rm et ls peuvent traiter eux-mêmes. Au moins un cas où ls montrera ce que rm ne peut pas supprimer concerne les autorisations de répertoire, et l'autre - les répertoires spéciaux . et ...

Autorisations de dossier

rm est une opération sur un répertoire, car en supprimant un fichier, vous modifiez le contenu du répertoire (ou en d'autres termes, la liste des entrées de répertoire, puisque le répertoire n'est rien de plus qu'une liste de noms de fichiers et d'inodes). Cela signifie que vous avez besoin de permissions d'écriture sur un répertoire. Même si vous êtes le propriétaire du fichier, sans les autorisations du répertoire, vous ne pouvez pas supprimer des fichiers. Le contraire est également vrai : rm peut supprimer des fichiers qui peuvent appartenir à d'autres, si vous êtes propriétaire du répertoire.

Vous pouvez très bien avoir des autorisations de lecture et d'exécution sur un répertoire, ce qui vous permettra de parcourir le répertoire et de visualiser son contenu, par exemple ls /bin/echo, mais vous ne pourrez pas faire rm /bin/echo sauf si vous êtes le propriétaire de /bin ou si vous élévez vos privilèges avec sudo.

Et vous verrez des cas comme celui-ci partout. Voici un cas similaire : https://superuser.com/a/331124/418028


Répertoires spéciaux '.' et '..'

Un autre cas spécial concerne les répertoires . et ... Si vous faites un ls . ou ls .., cela vous montrera joyeusement le contenu, mais les supprimer avec rm n'est pas autorisé :

$ rm -rf .
rm: refusing to remove '.' or '..' directory: skipping '.'

15voto

John O'Brien Points 21

Si vous tapez ls * puis rm *, il est possible que vous supprimiez plus de fichiers que ce que ls a montré - ils ont peut-être été créés dans le court intervalle de temps entre la fin de ls et le début de rm.

9voto

Magnus Hagander Points 8671

ls * et rm * ne sont pas responsables de l'expansion du glob - c'est fait par le shell avant de le passer à la commande.

Cela signifie que vous pouvez utiliser n'importe quelle commande avec la liste de fichiers étendue - donc je voudrais utiliser quelque chose qui fait le moins possible.

Une meilleure façon de faire cela (ou du moins, une autre façon) est de contourner l'intermédiaire.

echo * vous montrera exactement ce qui serait transmis à votre commande rm.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X