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 !

4voto

DevHugo Points 123

Si vous exécutez uniquement ls au lieu de ls -a, oui rm peut supprimer les fichiers cachés que vous n'avez pas vus avec ls sans -a.

Exemple :

En fonction de :

dir_test
 .test
 test2

ls dir_test : affichera uniquement test2

ls -A dir_test : affichera test2 + .test

rm -r dir_test : supprimera tout (.test + test2)

J'espère que cela vous aidera.

4voto

Que diriez-vous de :

$ mkdir what
$ cd what
$ mkdir -p huh/uhm ./-r
$ ls *
uhm
$ rm *
$ ls
-r
$ ls -R
.:
-r

./-r:

Essentiellement, les jokers se développant en choses commençant par - (ou les choses ajoutées manuellement commençant par - mais cela ressemble un peu à de la triche) peuvent être interprétées différemment par ls et rm.

4voto

alexis Points 1018

Il existe des cas particuliers où ce que ls affiche n'est pas ce que rm supprime. Un cas assez extrême, mais heureusement bénin, est lorsque l'argument que vous passez est un lien symbolique vers un répertoire : ls vous montrera tous les fichiers dans le répertoire lié, tandis que rm supprimera le lien symbolique, laissant le répertoire d'origine et son contenu inchangés :

% ln -s $HOME some_link
% ls some_link    # Affichera le contenu du répertoire  
bin    lib    Bureau ...
% rm some_link
% ls $HOME
bin    lib    Bureau ...

3voto

rexkogitans Points 291

Il y a déjà beaucoup de bonnes réponses, mais je veux ajouter quelques perspectives plus approfondies.

Posez-vous la question : combien de paramètres sont passés à ls, si vous écrivez

ls *

... ? Notez que la commande ls ne reçoit pas le * comme paramètre s'il y a des fichiers auxquels le * peut être étendu. Au lieu de cela, le shell effectue d'abord le globbing avant d'appeler la commande, donc la commande ls reçoit en réalité autant de paramètres qu'il y a de fichiers correspondant au globbing. Pour supprimer le globbing, mettez le paramètre entre guillemets.

Ceci est vrai pour n'importe quelle commande : echo * vs echo '*'.

Il y a un script, appelez-le countparams.sh pour tester l'effet. Il vous indique combien de paramètres lui ont été transmis et les liste.

#!/bin/bash
echo "Ce script a reçu $# paramètres."
arr=( "$@" )
for ((i=0;i<$#;i++)); do
        echo "Paramètre $((i+1)): ${arr[$i]}"
done

Rendez-le exécutable et exécutez ./countparams.sh *. Apprenez de sa sortie !

1voto

linuxuser27 Points 4095

La globulisation se fera de la même manière à chaque fois, si le contenu du répertoire est le même à ces deux moments différents.


Si vous voulez vraiment vérifier ce qui sera supprimé, utilisez rm -i *.txt. Il vous demandera séparément pour chaque fichier avant de le supprimer (d'essayer de le supprimer).

Ceci est garanti sûr contre les conditions de concurrence :
ls *.txt / un nouveau fichier est créé / rm *.txt
car vous êtes invité pour chaque fichier par le même programme qui effectue la suppression.


C'est trop encombrant pour un usage normal, et si vous alias rm à rm -i, vous vous retrouverez à utiliser \rm ou rm -f assez souvent. Cependant, il vaut au moins la peine de mentionner qu'il existe une solution à la condition de concurrence. (Elle est même portable sur des systèmes non-GNU : POSIX rm(1) spécifie l'option -i.)

Une autre option serait un tableau bash : to_remove=(*.txt), puis demander à l'utilisateur de confirmer (peut-être après avoir fait ls -ld -- "${to_remove[@]}"), puis rm -- "${to_remove[@]}". Ainsi, l'expansion globale n'est faite qu'une seule fois, et la liste est transmise textuellement à rm.

Une autre option pratiquement utilisable est GNU rm -I (page de manuel), qui demande confirmation si plus de 4 éléments sont supprimés. (Mais ne vous montre pas la liste, juste le total.) J'utilise alias rm='rm -I' sur mon bureau.

C'est une belle protection contre les erreurs de frappe en appuyant sur Entrée avec un motif à moitié tapé qui correspond à trop de choses. Mais l'utilisation de ls d'abord est généralement bonne dans un répertoire que vous possédez, ou sur un système monoutilisateur, et lorsqu'il n'y a pas de processus en arrière-plan qui pourraient créer de nouveaux fichiers de manière asynchrone. Pour vous prémunir contre les erreurs de frappe, ne tapez pas rm -rf /foo/bar/baz de gauche à droite. rm -rf / est un cas spécial, mais rm -rf /usr ne l'est pas ! Omettez la partie -rf, ou commencez par ls, et n'ajoutez la partie rm -rf qu'après avoir tapé le chemin.

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