Comment supprimer ce répertoire non supprimable?

40

J'ai décompressé un fichier tar corrompu et j'ai réussi à me retrouver avec un répertoire que je ne peux pas supprimer. Si j'essaie de le supprimer, il semble qu'il ne puisse pas être trouvé, mais lsil est présent, à la fois avec bash et avec python. comportement similaire, sauf juste après que j'essaie de le supprimer avec rm -rf, se lsplaint qu'il ne peut pas le trouver, puis il le répertorie (voir ci-dessous après rm -rf). La findcommande indique que le fichier est présent, mais je ne trouve toujours pas de moyen de le supprimer.
Voici mes tentatives:

Ici vous voyez les deux lset findconvenez que nous avons un répertoire,

rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -print0  
./mikeaâcnt 

Mais je ne peux pas le supprimer:

rl]$ find -maxdepth 1 -type d -empty -print0 |  xargs -0 rm -f -v 
rm: cannot remove `./mikeaâ\302\201\302\204cnt': Is a directory
rl]$ ls
mikeaâ??cnt

Je peux le cdfaire et c'est vide:

rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ pwd
.../rl/mikeaâcnt


mikeaâ^Á^Äcnt]$ cd ../
rl]$ ls
mikeaâ??cnt

voyez ci-dessous qu'il ne s'agit pas d'un fichier simple mais d'un répertoire. De plus, il lsse comporte de manière amusante après rm -rf qu'il indique qu'il ne trouve pas le fichier, puis le répertorie directement après:

rl]$ rm mikeaâ^Á^Äcnt/
rm: cannot remove `mikeaâ\302\201\302\204cnt/': Is a directory
rl]$ rm -rf  mikeaâ^Á^Äcnt/
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ 

Il s’agit donc d’une tentative avec python, le fichier est trouvé, mais le nom ne peut pas être utilisé comme nom pouvant être supprimé:

rl]$ python 
Python 2.6.6 (r266:84292, Jul 10 2013, 22:48:45) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import shutil
>>> os.listdir('.')
['mikea\xc3\xa2\xc2\x81\xc2\x84cnt']
>>> shutil.rmtree(os.listdir('.')[0] )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.6/shutil.py", line 204, in rmtree
    onerror(os.listdir, path, sys.exc_info())
  File "/usr/lib64/python2.6/shutil.py", line 202, in rmtree
    names = os.listdir(path)
OSError: [Errno 2] No such file or directory: 'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'

même lorsque j'utilise l'onglet de complétion, le nom qu'il prend n'est pas utilisable:

rl]$ rm -rf mikeaâ^Á^Äcnt 
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

en utilisant le nom que python montre avec bash, je reçois ceci:

rl]$ rm -rf "mikea\xc3\xa2\xc2\x81\xc2\x84cnt"
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Y a-t-il quelque chose que je puisse faire pour me débarrasser de ce répertoire corrompu? Le système de fichiers sous-jacent (NFS) semble fonctionnel et aucun autre problème n'a été signalé. Je n'ai eu aucun problème de ce type jusqu'à ce que le fichier tar corrompu.

EDIT: Ici, vous utilisez votre findpropre -execoption pour appelerrm

rl]$ find -maxdepth 1 -type d -empty -exec rm -f {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$

mais le fichier est toujours là (se lsplaint de ne pas pouvoir le trouver, mais le montre quand même)

2e édition:

rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} \;
find: `./mikeaâ\302\201\302\204cnt': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Le comportement est toujours inchangé, le fichier est toujours présent

3ème EDIT:

rl]$ ls
mikeaâ??cnt
rl]$ find -maxdepth 1 -type d -empty -exec rm -rf {} + 
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Il semble y avoir plus dans le nom que mikeaâcntde regarder le résultat de la tentative python mikea\xc3\xa2\xc2\x81\xc2\x84cntet cette capture d'écran:

ls sortie

4ème EDIT: Ceci est la tentative avec un joker:

rl]$ echo * 
mikeaâcnt
rl]$ echo mike* 
mikeaâcnt
rl]$ rm -rf mike*
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

et mon lieu:

rl]$  locale
LANG=en_US.utf8
LC_CTYPE="en_US.utf8"
LC_NUMERIC="en_US.utf8"
LC_TIME="en_US.utf8"
LC_COLLATE="en_US.utf8"
LC_MONETARY="en_US.utf8"
LC_MESSAGES="en_US.utf8"
LC_PAPER="en_US.utf8"
LC_NAME="en_US.utf8"
LC_ADDRESS="en_US.utf8"
LC_TELEPHONE="en_US.utf8"
LC_MEASUREMENT="en_US.utf8"
LC_IDENTIFICATION="en_US.utf8"
LC_ALL=

5ème édition:

rl]$ ls -i 
ls: cannot access mikeaâcnt: No such file or directory
? mikeaâ??cnt

mais aussi le comportement a changé, maintenant lset cd fais ceci:

rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt 
mikeaâcnt: No such file or directory.

Ce qui est arrivé après les tentatives de suppression, je pense qu'il pourrait y avoir des problèmes NFS comme suggéré dans l' une des réponses ici par vinc17.

6ème EDIT: Ceci est la sortie de lsofetls -a

rl] $ / usr / sbin / lsof mikeaâ ^ Á ^ Äcnt lsof: erreur d'état sur mikeaâ \ xc2 \ x81 \ xc2 \ x84cnt: aucun fichier ou répertoire de ce type

ci-dessus est faux, voici l' lsofappel correct : (rl est le répertoire parent)

rl]$ /usr/sbin/lsof | grep mike | grep rl 
tcsh      11926   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
lsof      14733   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
grep      14734   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
grep      14735   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
lsof      14736   mike  cwd       DIR   0,33     4096 19569249 /home/mike/mish/rl
rl]$ 

rl]$ ls -a
ls: cannot access mikeaâcnt: No such file or directory
.  ..  mikeaâ??cnt

7ème édition: mouvement ne fonctionnera pas, (je l' ai essayé avant tout cela, mais je n'ai pas sauvé la sortie), mais il a le même problème que lset rm avec le fichier.

8ème EDIT: ceci utilise les caractères hexa tels que suggérés:

 rl]$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a    mikea......cnt.
rl]$ rmdir $'mikea\6d69\6b65\61c3\a2c2\81c2\8463\6e74\0acnt' 
rmdir: failed to remove `mikea\006d69\006b651c3\a2c2\\81c2\\8463\006e74': No such file or directory
rl]$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt
rl]$

9ème édition: pour la statcommande:

 rl]$ stat  mikeaâ^Á^Äcnt 
stat: cannot stat `mikeaâ\302\201\302\204cnt': No such file or directory
 rl]$

Cela semble encore plus probable de toutes les sorties, il y a un bogue ou une autre mauvaise conduite de NFS comme suggéré dans les commentaires.

Edit 10: Ceci est la sortie de strace dans un résumé puisque sa taille, sa sortie ou ces deux commandes:

strace -xx rmdir ./* | grep -e '-1 E'`
strace -xx -e trace=file ls -li`

https://gist.github.com/mikeatm/e07fa600747a4285e460

Edit 11: Donc, avant ce qui précède, rmdirj'ai remarqué que je pouvais cdentrer dans le répertoire, mais après cela, rmdirje ne pouvais cdplus, comme hier. Les fichiers .et ..étaient présents:

rl]$ ls
mikeaâ??cnt
rl]$ cd mikeaâ^Á^Äcnt/
mikeaâ^Á^Äcnt]$ ls
mikeaâ^Á^Äcnt]$ ls  -a
.  ..
mikeaâ^Á^Äcnt]$ cd ../

Final Edit: J'ai vu un administrateur local à ce sujet et le problème a été résolu en se connectant au serveur lui-même et en le supprimant. L'explication de ceux-ci est qu'il pourrait y avoir un problème avec les jeux de caractères du nom inappropriés.

mike-m
la source
Y a-t-il une raison pour laquelle vous dirigez findla sortie vers une commande différente au lieu d'utiliser simplement son execoption?
HalosGhost
@HalosGhost il n'y avait aucune raison, voir edit pour plus d'informations sur votre question
mike-m
2
En tant que personne avec très peu d’expérience avec Unix et Linux, voici mon idée: essayez de renommer le répertoire en quelque chose sans ces symboles mv. Peut-être que vous pourrez le supprimer après cela Vous pouvez également essayer de déplacer le répertoire vers un dossier plus profond (éventuellement avec un caractère générique), puis de supprimer le dossier dans lequel vous l'avez déplacé.
Nzall
4
Je soupçonne que le répertoire n'existe qu'en mémoire sur le client et est disparu depuis longtemps sur le serveur. Avez-vous essayé de le démonter et de le remonter? Avez-vous essayé de redémarrer le client? Est-ce visible sur d'autres clients?
Kasperd
6
@ mike-m On dirait que vous avez touché un bogue NFS, probablement sur le serveur NFS. Soit ça ou système de fichiers corrompu sur le serveur. Je doute que vous puissiez vraiment faire autre chose que d’attendre que le ou les administrateurs du serveur NFS s’occupent de cela.
derobert

Réponses:

11

L'extrait suivant de cet essai explique potentiellement pourquoi ce répertoire refuse d'être supprimé:

NFSv4 exige que tous les noms de fichiers soient échangés en utilisant UTF-8 sur le fil. La spécification NFSv4, RFC 3530, stipule que les noms de fichiers doivent être encodés en UTF-8 dans la section 1.4.3: se trouve également dans la section 1.7.3 du RFC NFC 4.1 (RFC 5661), plus récente. Le client Linux NFS actuel passe simplement les noms de fichiers directement, sans conversion des paramètres régionaux actuels vers et depuis UTF-8. L'utilisation de noms de fichiers non UTF-8 peut être un réel problème sur un système utilisant un système NFSv4 distant. tout serveur NFS qui suit la spécification NFS est censé rejeter les noms de fichiers non UTF-8. Donc, si vous voulez vous assurer que vos fichiers peuvent effectivement être stockés d'un client Linux sur un serveur NFS, vous devez utiliser les noms de fichiers UTF-8. En d'autres termes,

UTF-8 est une approche à plus long terme. Les systèmes doivent prendre en charge UTF-8 ainsi que les nombreux codages plus anciens, ce qui permet aux utilisateurs de passer à UTF-8. Pour utiliser «UTF-8 partout», tous les outils doivent être mis à jour pour prendre en charge UTF-8. Il y a des années, c'était un gros problème, mais à partir de 2011, il s'agit essentiellement d'un problème résolu, et je pense que la trajectoire est très claire pour ces quelques systèmes à la traîne.

Toutes les séquences d'octets ne sont pas légales UTF-8, et vous ne voulez pas avoir à comprendre comment les afficher. Si le noyau applique ces restrictions en s'assurant que seuls les noms de fichiers UTF-8 sont autorisés, il n'y a alors aucun problème ... tous les noms de fichiers seront des fichiers UTF-8 légaux. La fonction C utf8_check C de Markus Kuhn permet de déterminer rapidement si une séquence est valide en UTF-8.

Le système de fichiers doit exiger que les noms de fichiers respectent certaines normes, non pas à cause d'un besoin pervers de contrôler les personnes, mais simplement afin que les noms puissent toujours être affichés correctement à une date ultérieure. Le manque de normes rend les choses plus difficiles pour les utilisateurs, pas plus faciles. Pourtant, le système de fichiers ne force pas les noms de fichiers à être UTF-8, de sorte qu'il peut facilement être corrompu.

Timothy Martin
la source
Cela semble faire écho à l'explication fournie par les administrateurs locaux, je vais marquer cela comme étant la réponse fournie par l'explication des administrateurs. Voir mon montage final
mike-m
19

Une façon de supprimer des fichiers / répertoires comme celui-ci est par leur référence d'inode.

Pour trouver les inodes des éléments dans le répertoire courant:

ls -i
14813568 mikeaâcnt

Pour supprimer ceci:

find . -inum 14813568 -delete
Nicolaï
la source
s'il vous plaît voir 5ème édition.
mike-m
4
Non, cela ne supprime pas les fichiers par leur inode. Ceci recherche un nom de fichier pour l'inode donné, puis supprime le fichier par son nom. Cela ne peut pas aider ici, car une tentative a déjà été faite avec le nom correct (à côté d’autres tentatives avec un nom incorrect).
Gilles 'SO- arrête d'être méchant'
@ Gilles - techniquement, il recherche un inode dentry et renvoie un nom de fichier, mais je suis d'accord.
mikeserv
1
@ Nicolai n'aide pas pour moi. Répertoire pas message vide apparaît.
DiffracteD
1
Ouais, ah, histoire amusante à ce sujet: le fichier que je tente de supprimer a ?pour référence inode. Comment le supprimez-vous alors?
La poursuite de Monica le
7

Vous ne devez pas utiliser de caractères non-ASCII dans la ligne de commande car, comme vous avez pu le constater, pour une raison quelconque, ils ne correspondront pas nécessairement au nom du fichier (Unicode propose différentes manières d’exprimer des lettres accentuées). Quelque chose comme:

rm -rf mike*

devrait fonctionner puisque le nom du fichier est directement généré par le shell. Mais assurez-vous qu'il n'y a qu'une seule correspondance (faites une echo mike*première pour confirmer).

Eh bien, si cela cdfonctionne, il n'y a aucune raison pourquoi rmou lsdevrait dire No such file or directory, de sorte que le problème peut être au niveau du système de fichiers.

Remarque: N'utilisez pas lspour rechercher si un répertoire est vide, mais ls -a.

Le répertoire peut toujours être utilisé par un autre processus (y compris s'il s'agit du cwd d'un processus). IMHO, c'est pourquoi il "existe toujours" mais peut générer des erreurs, par exemple avec ls; lsofpeut vous donner des informations, mais avec NFS, vous devez trouver quelle machine l’utilise. Surtout avec NFS, cela peut donner d’étranges erreurs. ls -adans le répertoire parent peut vous montrer des .nfs*fichiers / répertoires dans certains cas.

Quand vous obtenez:

$ ls
ls: cannot access mikeaâcnt: No such file or directory
mikeaâ??cnt

Je soupçonne que le fichier existe toujours dans la table des répertoires en raison de la mise en cache NFS et / ou parce qu'il est utilisé par un autre processus, mais sans informations associées. Lorsque vous lsessayez d'obtenir des informations sur le fichier lui-même, une erreur se produit car le fichier lui-même n'existe plus (il ne se trouve que dans la table des répertoires), d'où l'erreur affichée. Puis lssort le nom de fichier car il se trouve dans la table des répertoires. Le fait que vous ayez des points d'interrogation dans un cas mais pas dans l'autre est dû à un bug d'affichage de lsIMHO (sans rapport avec votre problème).

vinc17
la source
J'avais essayé un joker plus tôt, cela ne fonctionnait pas, et je n'ai pas réussi à poster cette tentative dans ma question, je mettrai à jour le résultat
mike-m
Voir ma troisième édition. IMHO cela est dû à NFS (probablement pas à la corruption, mais à une mauvaise mise en cache) et peut-être au fait qu'un autre processus utilise le répertoire. Dans certains cas, il faut tout redémarrer (le serveur et les clients).
vinc17
Cela pourrait peut-être expliquer des choses, mais je ne peux pas être sûr car je n'ai pas le privilège de le prendre pour des tests. Voir la 5ème édition.
mike-m
1
@ vinc17 S'il vous plaît, n'utilisez pas "EDIT" dans votre réponse, car pour les nouveaux lecteurs, cela n'a pas de sens (il existe déjà une historique des modifications)
Bernhard
iv ajouté quelques sorties de lsof, je ne sais pas s'il peut vous dire quoi que ce soit,
mike-m
3

J'ai personnellement testé l'utilisation de findla -execdirective:

$ mkdir -p mikeaâcnt
$ ls
mikeaâcnt
$ find -maxdepth 1 -type d -empty -exec rm -rf {} +
$ ls
$ 

Le dossier a été correctement créé et correctement supprimé.

Comme l'a souligné @Igeorget , il existe une méthode encore plus simple si vous utilisez GNU find:

$ find -maxdepth 1 -type d -empty -delete

J'ai aussi testé cette commande et elle fonctionne correctement

HalosGhost
la source
Et si vous utilisez la recherche de GNU, il y a aussi une -deleteoption.
lgeorget
S'il vous plaît voir 3ème édition,
mike-m
1

J'ai eu le même problème, je crois. J'ai vu le problème plus tôt avec un nom de fichier de . lsdans ce cas, affiche le fichier sous la forme â??, mais j'ai pu le supprimer avec rm ☃.

Cela m'a amené à convertir le nom incorrect en nom correct de la manière suivante:

Commencez par obtenir les octets du nom de fichier:

$ ls --show-control-chars | xxd
0000000: 6d69 6b65 61c3 a2c2 81c2 8463 6e74 0a    mikea......cnt.

Décodez ensuite ces octets en UTF-8 pour obtenir les points de code Unicode, en utilisant l'entrée hexadécimale de ce site Web, par exemple: http://software.hixie.ch/utilities/cgi/unicode-decoder/utf8-decoder

U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX character (&#x00E2;)
U+0081 <control> character (&#x0081;)
U+0084 <control> character (&#x0084;)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character

Notez que tous sont en dessous de la limite d'octet. Nous obtenons les octets suivants:

6D 69 6B 65 61 E2 81 84 63 6E 74

Si nous traitons cette séquence à UTF-8, nous obtenons:

U+006D LATIN SMALL LETTER M character
U+0069 LATIN SMALL LETTER I character
U+006B LATIN SMALL LETTER K character
U+0065 LATIN SMALL LETTER E character
U+0061 LATIN SMALL LETTER A character
U+2044 FRACTION SLASH character (&#x2044;)
U+0063 LATIN SMALL LETTER C character
U+006E LATIN SMALL LETTER N character
U+0074 LATIN SMALL LETTER T character

Et ainsi votre nom de fichier est:, mikea⁄cntavec une fraction de barre oblique au lieu d'une normale. Vous pouvez maintenant passer ce nom à rmdir.

mvdnes
la source
C’est ingénieux, si je revois ça encore une fois, il faut garder cela à l’esprit. bon un. +1
mike-m
0

Après avoir obtenu le code hexadécimal correct du nom du fichier / dossier (quelle que soit la méthode que l’on juge appropriée, je peux choisir ls --show-control-chars | xxd), une construction spéciale doit être utilisée pour adresser ces caractères lors de l’exécution sous bash:

rmdir $'mikea\xc3\xa2\xc2\x81\xc2\x84cnt'

Sinon, les barres obliques inverses sont traitées comme des barres obliques inverses à la vanille.

Abel Cheung
la source
S'il vous plaît jeter un oeil à mon édition (8ème édition)
mike-m
@ mike-m Bien sûr, cela n'existe pas, car lsinclut les nouvelles lignes dans les données de sortie et le "cnt" est dupliqué. Peut-être que vous pouvez essayer directement de copier et coller la ligne dans ma réponse et voir si elle est efficace?
Abel Cheung
Nope, toujours ceci: `` `rl] $ rmdir $ 'mikea \ xc3 \ xa2 \ xc2 \ x81 \ xc2 \ x84cnt' rmdir: n'a pas réussi à supprimer le` mikeaâ \ 302 \ 201 \ 302 \ 204cnt ': Aucun fichier ou répertoire de ce type `` `
mike-m
Dans ce cas, il s’agit très probablement d’une combinaison de problèmes NFS et de paramètres régionaux empêchant la plupart des utilitaires système de transmettre des octets non UTF8 incorrects. Et il semblerait que la suppression d'inode ait aggravé la situation. Pour le moment, la seule façon dont je puisse penser est de configurer votre système pour un environnement dépourvu de paramètres régionaux (utilisez les paramètres régionaux «C» pour les variables LC_*et LANGenv) et de monter NFS sans aucune option de jeu de caractères.
Abel Cheung
0

Avez-vous essayé d'utiliser rm -rf ./mikeaâcntou rm -rf "./mikeaâcnt"ou un chemin absolu? Aussi au lieu de rm, essayez rmdir ./mikeaâcnt.

Walsht
la source
Une partie du problème est que les caractères dans mikeaâcntne semblent pas être le nom du fichier, mais ce qui ls s'affiche, voir la 3ème édition
mike-m
0

Avez-vous essayé d'obtenir l'inode de ce fichier avec stat:

stat mike*

Cela devrait vous donner le numéro d’inode (et d’autres données), et vous pourrez ensuite essayer de le supprimer.

rsuarez
la source
iv a ajouté une modification avec statbehavior,
mike-m le
0

J'ai eu des problèmes similaires. Avez-vous Gnome, KDE ou une sorte de Xwindow DM?. Si vous ouvrez votre fichier broser et supprimez le fichier à partir de là.

Ça devrait marcher.

Je voudrais voir une solution à partir de la ligne de commande, mais dans mon cas et après avoir perdu beaucoup de temps à essayer de comprendre comment la supprimer de la ligne de commande, j’ai trouvé que c’était aussi simple que de supprimer tout autre fichier de Nautilus ou tout autre explorateur de fichiers (en réalité, j’ai seulement essayé avec Nautilus).

YoMismo
la source