삭제할 수 없는 디렉터리를 삭제하는 방법은 무엇입니까?

삭제할 수 없는 디렉터리를 삭제하는 방법은 무엇입니까?

손상된 tar 파일의 압축을 풀고 삭제할 수 없는 일부 디렉토리를 얻었습니다. 삭제하려고 하면 찾지 못하는 것 같지만 lsbash와 Python 모두에서 비슷한 동작이 발생합니다. 단 rm -rf, 를 사용하여 삭제하려고 시도했지만 ls찾을 수 없다고 불평한 다음 목록에 표시되었습니다(아래 참조 rm -rf). 명령 find을 실행하면 파일이 존재한다고 표시되지만 여전히 삭제 방법을 알 수 없습니다.
내 시도는 다음과 같습니다.

여기에서 두 가지를 모두 확인 ls하고 find디렉토리가 있다는 데 동의할 수 있습니다.

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

하지만 삭제할 수는 없습니다.

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

할 수 있지만 cd비어 있습니다.

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


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

아래를 보세요. 단순한 파일이 아니라 디렉터리인데, ls파일을 찾을 수 없다는 메시지가 표시되고 목록만 나열되면 이상하게 작동합니다.rm -rf

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]$ 

다음은 Python을 사용한 시도입니다. 파일을 찾았지만 이름을 삭제 가능한 이름으로 사용할 수 없습니다.

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'

탭 완성 기능을 사용해도 선택한 이름이 작동하지 않습니다.

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

Python을 사용하여 bash에 이름을 표시하면 다음과 같은 결과를 얻을 수 있습니다.

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

손상된 디렉토리를 제거하기 위해 제가 할 수 있는 일이 있나요? 기본 파일 시스템(NFS)은 제대로 작동하는 것으로 보이며 다른 문제는 보고되지 않았습니다. 손상된 tar 파일로 인해 이전에는 그러한 문제가 발생하지 않았습니다.

편집: 여기에서는 find내 자신의 -exec옵션을 사용하여 전화를 겁니다.rm

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]$

하지만 파일은 아직 거기에 있습니다. ( ls찾을 수 없다고 불평하지만 어쨌든 표시됩니다)

두 번째 편집:

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

동작은 동일하게 유지되고 파일은 여전히 ​​존재합니다.

세 번째 편집:

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

mikeaâcntPython 시도의 출력 mikea\xc3\xa2\xc2\x81\xc2\x84cnt과 이 스크린샷을 보는 것보다 이름이 더 중요해 보입니다 .

ls 출력

네 번째 편집: 와일드카드를 사용한 시도는 다음과 같습니다.

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

내 로케일:

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=

다섯 번째 편집:

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

그리고 동작이 변경되어 이제 다음을 ls수행합니다 .cd

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.

삭제를 시도한 후에 이런 일이 발생했습니다. 답변 중 하나에서 제안한 대로 NFS 문제일 수 있습니다.여기vinc17이 제공했습니다.

lsof6번째 편집: 이것은 및ls -a

rl]$ /usr/sbin/lsof mikeaâ^Á^äcnt lsof: mikeaâ\xc2\x81\xc2\x84cnt의 상태 오류: 해당 파일 또는 디렉터리가 없습니다.

위의 내용은 잘못되었습니다. 올바른 lsof호출은 다음과 같습니다. (rl은 상위 디렉터리입니다.)

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

일곱 번째 편집: 이동이 작동하지 않습니다. (이전에 시도했지만 출력을 저장하지 않았습니다.) 파일에도 동일한 ls문제가 있습니다 rm .

여덟 번째 편집: 제안된 대로 16진수 문자를 사용합니다.

 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]$

아홉 번째 편집: stat명령의 경우:

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

모든 출력으로 판단하면 주석에서 제안한 대로 버그나 기타 NFS 오작동이 있을 가능성이 높습니다.

편집 10: strace 출력의 요점은 다음과 같습니다. 출력이 너무 크기 때문에 출력 또는 다음 두 명령입니다.

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

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

편집 11: 그래서 위의 이전에는 디렉토리에 들어갈 rmdir수 있다는 것을 알았지 만 그 이후에는 어제와 비슷하게 더 이상 들어갈 수 없었습니다 . 파일이 존재 합니다.cdrmdircd...

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

최종 편집: 로컬 관리자가 이 문제를 처리하고 서버 자체에 로그인하여 삭제하는 방식으로 처리하는 것을 보았습니다. 그들의 설명은 이름에 부적절한 문자 집합이 문제일 수 있다는 것이었습니다.

답변1

이와 같은 파일/디렉토리를 삭제하는 한 가지 방법은 inode 참조를 이용하는 것입니다.

현재 디렉터리에 있는 요소의 인덱스 노드를 찾으려면 다음을 수행하세요.

ls -i
14813568 mikeaâcnt

이 콘텐츠를 삭제하려면:

find . -inum 14813568 -delete

답변2

다음 내용은 에서 가져온 것입니다.이 기사디렉토리 삭제를 거부하는 이유를 설명할 수 있습니다.

NFSv4에서는 UTF-8을 사용하여 네트워크를 통해 모든 파일 이름을 교환해야 합니다. NFSv4 사양 RFC 3530에는 섹션 1.4.3에 파일 이름이 UTF-8로 인코딩되어야 한다고 명시되어 있습니다. "약간의 변형이 있지만 파일 및 디렉터리 이름은 국제화의 기본 사항을 처리하기 위해 UTF-8로 인코딩됩니다." NFS 4.1 RFC(RFC 5661)의 섹션 1.7.3에서도 찾을 수 있습니다. 현재 Linux NFS 클라이언트는 현재 로케일과 UTF-8 간의 변환 없이 파일 이름을 직접 전달합니다. 원격 NFSv4 시스템을 사용하는 시스템에서는 UTF-8이 아닌 파일 이름을 사용하는 것이 실제 문제가 될 수 있습니다. NFS 사양을 따르는 모든 NFS 서버는 UTF-8이 아닌 파일 이름을 거부해야 합니다. 따라서 파일이 실제로 Linux 클라이언트에서 NFS 서버로 저장될 수 있는지 확인하려면 현재 UTF-8 파일 이름을 사용해야 합니다. 즉, 어떤 사람들은 Linux가 파일 이름에 특정 문자 인코딩을 사용하도록 강요하지 않는다고 생각하지만 실제로는 어떤 경우에는 이미 파일 이름에 UTF-8 인코딩을 사용해야 합니다.

UTF-8은 장기적인 접근 방식입니다. 시스템은 사람들이 UTF-8로 전환할 수 있는 시간을 제공하기 위해 UTF-8은 물론 많은 이전 인코딩도 지원해야 합니다. UTF-8을 "어디서나" 사용하려면 UTF-8을 지원하도록 모든 도구를 업데이트해야 합니다. 몇 년 전에는 이것이 큰 문제였지만 2011년 현재는 대부분 해결된 문제이며 소수의 후행 시스템에 대한 궤도는 꽤 분명하다고 생각합니다.

모든 바이트 시퀀스가 ​​합법적인 UTF-8은 아니며 이를 표시하는 방법을 알아낼 필요가 없습니다. 커널이 이러한 제한을 적용하여 UTF-8 파일 이름만 허용한다면 문제가 없을 것입니다. 모든 파일 이름은 합법적인 UTF-8이 될 것입니다. Markus Kuhn의 utf8_check C 함수는 시퀀스가 ​​유효한 UTF-8인지 빠르게 확인할 수 있습니다.

파일 시스템은 특정 표준을 준수하는 파일 이름을 요구해야 합니다. 이는 사람을 제어하려는 일부 사악한 필요성 때문이 아니라 나중에 이름이 올바르게 표시될 수 있도록 하기 위한 것입니다. 표준이 부족하면 사용자가 일을 더 쉽게 하기는커녕 더 어렵게 만듭니다. 하지만 파일 시스템에서는 파일 이름을 UTF-8로 강제하지 않기 때문에 쓰레기가 나타나기 쉽습니다.

답변3

보시다시피 어떤 이유로든 파일 이름과 반드시 ​​일치할 필요는 없기 때문에 명령줄에 ASCII가 아닌 문자를 사용하면 안 됩니다(유니코드에는 악센트 문자를 표현하는 다양한 방법이 있습니다). 그것은 다음과 같습니다:

rm -rf mike*

파일 이름은 셸에서 직접 생성되므로 이 방법이 작동합니다. 하지만 일치하는 항목이 하나만 있는지 확인하세요( echo mike*먼저 확인).

글쎄, cd작동한다면 이유가 없거나 말해야 하므로 rm문제 는 아마도 파일 시스템 수준에 있을 것입니다.lsNo such file or directory

ls참고: 디렉토리가 비어 있는지 찾는 데 사용하지 말고 대신 를 사용하십시오 ls -a.

디렉터리는 다른 프로세스에서 계속 사용될 수 있습니다(프로세스의 cwd인 경우 포함). IMHO 이것이 여전히 "존재"하지만 오류가 발생할 수 있는 이유입니다. 예를 들어 ls일부 lsof정보를 제공할 수 있지만 NFS에서는 이를 사용하는 머신을 찾아야 합니다. 특히 NFS에서는 이상한 오류가 발생할 수 있습니다. 어떤 경우에는 파일/디렉토리가 ls -a상위 디렉토리에 나타날 수 있습니다 ..nfs*

당신이 그것을 얻을 때:

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

파일이 아직 존재하는 것 같습니다.목차NFS 캐싱 및/또는 다른 프로세스에서 사용되기 때문에 관련 정보가 없습니다. ls파일 자체에 대한 정보를 얻으려고 하면 파일 자체가 더 이상 존재하지 않기 때문에(디렉토리 테이블에만 존재함) 오류가 발생하므로 오류를 표시합니다. 그런 다음 ls파일 이름을 디렉터리 테이블에 있는 그대로 출력합니다. 한 경우에는 물음표가 있지만 다른 경우에는 물음표가 없다는 사실은 ls디스플레이 버그 IMHO(귀하의 질문과 관련 없음) 때문입니다.

답변4

나는 같은 문제에 직면했다고 생각합니다. 이전에 호출된 파일을 본 적이 있습니다 . ls이 경우 파일은 으로 표시되지만 â??를 사용하여 삭제할 수 있습니다 rm ☃.

이로 인해 잘못된 이름을 올바른 이름으로 변환하기 위해 다음과 같은 접근 방식이 사용되었습니다.

먼저 파일 이름의 바이트를 가져옵니다.

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

그런 다음 이러한 바이트는 UTF-8로 디코딩되어 유니코드 코드 포인트를 얻습니다. 예를 들어 이 웹 사이트의 16진수 입력을 사용합니다.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

이는 바이트 경계 아래에 있습니다. 우리는 다음 바이트를 얻습니다:

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

이 시퀀스를 UTF-8로 처리하면 다음과 같은 결과를 얻습니다.

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

따라서 파일 이름은 다음과 같습니다. mikea⁄cnt일반 슬래시 대신 분수 슬래시가 사용됩니다. 이제 이 이름을 에 전달할 수 있습니다 rmdir.

관련 정보