파일 이름이 인쇄되지 않은 파일을 가진 파일을 삭제하는 방법


46

어떻게 든 파일 이름이없는 파일을 만들었습니다. 다음 스레드 에서 파일에 대한 자세한 정보를 얻는 방법에 대한 정보를 찾았습니다 .

그러나 나열된 제안 중 일부를 시도했지만 파일을 삭제할 수 없습니다. 내가 무엇을 만들 었는지 잘 모르겠지만 xml 파일을 복사하는 중 발생했습니다.

파일에 대한 일부 정보는 다음과 같습니다.

> ls -lb
total 296
-rw-r--r--   1 voyager  endeavor  137627 Jan 12 12:49 \177

> file *
:               XML document

> ls -i
 417777   

나는 inum 스위치를 사용하여 찾은 다음 그것을 제거하는 가장 바보 같은 방법처럼 보이는 것처럼 rm으로 파이프했습니다. 그러나 아래 링크 된 스레드의 맨 아래에 주어진 예는 저에게 실패했습니다. 예는 다음과 같습니다.

> find -inum 41777 -exec ls -al {} \;
find: illegal option -- i
find: [-H | -L] path-list predicate-list

그래서 다음과 같이 경로 목록을 먼저 사용해 보았지만 작동하지 않았습니다.

> find . -inum 41777 -exec ls -al {} \;

인쇄 할 수없는 문자 \ 177이 무엇인지 또는 어떻게 rm명령에 전달할 수 있는지 확실하지 않지만이 파일을 삭제하려고 시도 할 때 다른 파일 / 디렉토리를 엉망으로 만들지 않기를 정말로 원합니다.


1
\177ASCII DEL문자입니다.
Keith Thompson

9
417777! = 41777
CVn

훌륭한 지적 마이클. 아마도 내 명령이 작동하지 않은 이유 일 것입니다.
Mr Moose

@KeithThompson 선행없이 8 진수 0입니까?
cat

1
@cat :이 맥락에서 그렇습니다. 문자열 및 문자 리터럴에 대한 C 구문을 따릅니다.
Keith Thompson

답변:


46

파일 이름이 있지만 인쇄 할 수없는 문자로 만들어졌습니다. ksh93, bash, zsh, mksh 또는 FreeBSD sh를 사용하는 경우 인쇄 할 수없는 이름을 지정하여 제거 할 수 있습니다. 먼저 이름이 올바른지 확인 ls -ld $'\177' 하십시오. 올바른 파일이 표시되면 rm을 사용하십시오.rm $'\177'

또 다른 (좀 더 위험한) 접근 방식은을 사용하는 것 rm -i -- *입니다. -i 옵션 rm을 사용하면 파일을 제거하기 전에 확인이 필요하므로 보관하려는 모든 파일을 제외하고 건너 뛸 수 있습니다.

행운을 빕니다!


1
rm -i *이 경우에는 효과 가 없었을 것으로 생각됩니다 . 줄 바꿈 때문에 쉘은 파일 이름으로 인식되지 않는 것으로 확장 *됩니다 rm.
Keith Thompson

6
@KeithThompson : 쉘의 글로벌 확장은 더 이상 해석되지 않습니다. 확장 이름에 개행 문자가 포함되어 있지 않으면 개행 문자가 없습니다.
Christoffer Hammarström

@ ChristofferHammarström : 흠. 몇 가지 실험을 해보고 더 언급하겠습니다.
Keith Thompson

@ ChristofferHammarström : 파일 이름에 개행 문자가 포함되어 있으므로 확장 된 이름에 개행이 있습니다. 그러나 내가 과소 평가 한 것 같다 bash및 GNU rm. 내 시스템에서 rm *, rm -i *그리고 rm Ctrl-V DEL TAB ENTER모든 작업이 제대로, 파일 이름이 개행 문자를 (내가 사용 포함 된 경우에도 "\177foo\nbar\n"). 일부 명령은 이러한 파일 이름을 잘 처리하지 못하지만 GNU 도구는 강력 해 보입니다. 동일한 도구의 GNU 이외 버전도 작동하지 않을 수 있습니다. 어쨌든이 답변의 다양한 트릭은 알고 유용합니다.
Keith Thompson

1
@KeithThompson, 모든 쉘은 Bash뿐만 아니라 파일 globbing을 올바르게 처리하며 rmGNU인지 여부에 관계없이 어떤 형태의 단어도 분할 rm하지 않습니다. 쉘은 globs를 확장하고 호출 된 명령을 실행할 때 결과 파일 이름을 널로 구분 된 인수 (C 코드에서)로 전달합니다. 위험한 것은 줄 바꿈 문자 를 구분 기호로 사용하는 파일 목록 을 파이프 하는 것입니다 . find의 출력을 반복하는 것이 왜 나쁜 습관입니까?를 참조하십시오 .
와일드 카드

23

사용 vim하는 사람들을 위해 현재 작업 디렉토리에서 실행하십시오.

$ vim ./ 

화살표 키 또는로 파일을 탐색하십시오 j/k. 그런 다음를 Shift+D눌러 삭제를 확인하십시오 y.


나는 일반적으로 vim을 무서워하지만, 실제로 효과가 있었다
tofutim

9

파일 이름을로 전달하는 방법이 rm있을 수 있지만, 엉망이 될 경우 GUI 파일 관리자를 사용할 수 있습니다. Emacs는 디렉토리 편집 모드가 설치되어 있다면 사용할 수 있습니다 :

  1. 에서 폴더를여십시오 emacs. 을 실행 emacs /path/to/folder하거나 emacs를 열고 Esc+ x를 누르고 실행 dired하면 경로를 묻는 메시지가 나타납니다.

    http://so.mrozekma.com/unix-dired-delete1.png

  2. 삭제하려는 파일이있는 행으로 이동하고를 누릅니다 d. D파일 옆의 왼쪽 여백에 표시되어야 합니다.

    http://so.mrozekma.com/unix-dired-delete2.png

  3. 를 눌러 x변경 사항을 저장하십시오. 파일을 삭제하라는 메시지가 표시됩니다. 누릅니다 y:

    http://so.mrozekma.com/unix-dired-delete3.png


1
좋은 생각처럼 보이지만이 컴퓨터에서 이맥스를 찾을 수없는 것 같습니다. 거룩한 전쟁이 시작될 위험에 처해 있습니다.
Mr Moose

2
vim이것을 사용 하는 사람들을 위해 현재 작업 디렉토리에서 실행 vim ./하고 화살표 키로 파일을 탐색하십시오. 그런 다음를 Shift+D눌러 삭제를 확인하십시오 y.

@ 헤세 와우. 내가 vim지지 할 것으로 예상되지 않은 것
Michael Mrozek

1
@MichaelMrozek은 동의했다.이 기능은 내가 직업적으로 발견하는 경향이있다.

1
Tim

8

file *쉘 glob ( *)가이 파일을 선택할 수 있다는 것을 이미 증명 했으므로 이제 rm해당 glob를 수행하십시오.

  • 파일이있는 디렉토리로 변경하십시오.
  • 운영 rm -i *
  • n보이지 않는 파일 이름을 가진 파일을 제외한 모든 파일에 입력하십시오.

7

실제로 파일 이름이 있지만 인쇄 할 수없는 문자로 만들어졌습니다.

쉬운 방법은 쉘 완성에 의존하는 것입니다 Tab. "이상한"파일 이름이 삽입 될 때 까지을 반복해서 누릅니다 . 가능한 완료 사이를 순환하도록 쉘을 구성해야합니다.

  • 배쉬에서는 호출 할 필요 menu-complete보다는 기본에 구속되지 않으며, complete결합되어, Tab기본적으로. 또는 Esc *모든 파일에 대한 완성을 삽입하고 명령 줄에서 삭제하지 않으려는 것을 제거하는 데 사용하십시오.
  • zsh에서는 기본 설정이 정상입니다. 가지고 setopt auto_menu있거나 setopt menu_complete설정 해야합니다 .

셸에서 완성이 도움이되지 않으면 rm -i -- *이 특정 파일을 제외하고“아니오”로 전화를 걸어 대답 할 수 있습니다 . 파일 이름이 인쇄 가능한 문자로 시작하지 않으면 첫 번째 문자가 인쇄 가능한 문자 세트가 아닌 파일로 일치를 제한 할 수 있습니다.

rm -i [!!-~]*
rm -i [![:print:]]*
rm -i -- [!a-z]

패턴이 옵션으로 취급 -f되는 파일과 일치 할 수 rm있습니다.

또 다른 방법은 ls -i파일의 inode (아이 노드는 주어진 파일 시스템에서 파일을 고유하게 식별)를 찾은 다음 find -inum해당 특정 파일에서 작동 하도록 호출 하는 것 입니다. 이 방법은 디렉토리에 많은 파일이있을 때 주로 유용합니다.

ls -i
# note the inode number 12345
find . -xdev -inum 12345 -delete

옵션 find이없는 경우 다음을 -delete호출하십시오 rm.

find . -xdev -inum 12345 -exec rm -- {} \;

(예, 대부분의 게시물이 이미 게시되어 있음을 알고 있습니다. 그러나 관련 정보가 포함 된 답변으로 인해 이전보다 더 복잡해졌습니다.)


4

를 사용 echo -e하여 캐릭터를 얻은 \177다음 xargs에 전달해보십시오 rm. echo십진수 이스케이프를 사용하지 않으므로 16 진수로 변환 하십시오 177. echo다음 \0전에 (문자, null 바이트가 아님) 가 필요합니다 .

echo -ne '\0177\0' | xargs -0 rm

\ xb1 \ 0이 \ 177의 16 진 표현이라고 말하고 있습니까?
Mr Moose

@MrMoose \xb1는 decimal 177이며 \0null로 끝나고 개행으로 끝나는 이름 대신 null로 끝나는 이름을 사용하도록 -0지시 xargs합니다.
Kevin

SunOS에서 bash를 사용하고 있으며 명령을 시도했을 때 xargs : illegal option-0을 얻었습니다. 맨 페이지를보고 null 종료 옵션을 볼 수 없었습니다. 그래도 문제에 대한 해결책을 얻었습니다. 답변으로 표시된 답변을 참조하십시오.
Mr Moose

여러분 echo,있는 그대로, 전송 xargs를에 파일 이름을 한 다음에 rm... 두 번째 파일 이름입니다 \n.. 오류, 또는 그 이름 ( '\ n')의 파일 삭제 중 하나에이 결과
피터. O

@perer 네, 방금 알았습니다. -n줄 바꿈을 제거하기 위해 추가 했습니다.
Kevin

3

파일 이름 있음을 보증 할 수 있습니다 . 인쇄 할 수없는 문자가 포함 된 이름 일뿐입니다.

경우 rm작동하지 않았다, 다음 출력을 사용하여 find-inum의 인수로 옵션 rm도움말을 가능성이 없습니다; rm동일한 문제로 동일한 인수를에 전달합니다 .

파일은 그 디렉토리에있는 유일한 파일입니까?

가장 먼저 시도 할 것은 cd디렉토리에 들어가서을 입력 rm ./한 다음 Tab 키를 누르는 것입니다. 이렇게하면 인수를 파일의 실제 이름으로 확장해야하며, 앞에서 ./rm인수를 파일 이름 이외의 것으로 해석 하지 않아야합니다 .

또 다른 해결책은 cd상위 디렉토리에 대한 다음 디렉토리에서 rm -r(또는 필요한 경우 rm -rf)를 사용하는 것입니다. 이름과 상관없이 디렉토리와 그 내용을 모두 제거해야합니다. 그런 다음 mkdir디렉토리를 다시 작성 chmod하고 권한을 복원 하는 데 사용할 수 있습니다 .

편집하다 :

ls -lb출력을 다시 보면 파일 이름이 ASCII DEL문자 (치명적이지는 않지만 나쁘지 않음)로 시작 하고 하나 이상의 줄 바꿈 문자 (실제로 나쁨)가 포함되어 있다고 생각합니다 . 내가 알 수있는 한 rm명령은 줄 바꿈을 파일 이름의 일부로 해석 할 수 없습니다.

그러나 unlink()시스템 호출은 가능합니다. 다음은 현재 디렉토리의 파일을 반복하여 제거할지 여부를 묻는 Perl 스크립트입니다. rm파일을 제거하는 것과 같은 외부 명령을 사용하지 않으므로 파일 시스템이 지원하는 재미있는 문자 (ASCII NUL및 이외의 문자)를 처리 할 수 ​​있어야합니다 /.

포함하는 디렉토리 에서 rm -r또는 수행중인 rm -rf디렉토리는 여전히 작동하지만 단일 파일을 제거하려는 경우이를 시도 할 수 있습니다.

#!/usr/bin/perl

use strict;
use warnings;

opendir my $DIR, '.' or die ".: $!\n";
my @files = sort grep { -f } readdir $DIR;
closedir $DIR;

foreach my $file (@files) {
    my $pfile = printable($file);
    print "Remove $pfile? ";
    my $answer = scalar <STDIN>;
    if ($answer =~ /^[Yy]/) {
        print "Removing $pfile\n";
        unlink $file or warn "Unable to remove $pfile: $!\n";
    }
}

sub printable {
    my($s) = @_;
    $s =~ s/[^ -~]/?/g;
    return $s;
}

(또 다른 해결책은 유지하려는 디렉토리에 다른 파일이있는 경우 다른 모든 파일을 임시 디렉토리로 이동 한 다음 디렉토리를 압축하고 다시 작성하고 다른 파일을 다시 이동하는 것입니다.)

(아, 그리고 그 파일을 만들기 위해 무엇을 하든지 다시는하지 마십시오!)


1

명령을 사용하여 해당 파일을 정확하게 찾을 find수 있으면 -delete술어 를 사용할 수 있습니다 . -deletefind 명령의 마지막 매개 변수를 주의하십시오. 그렇지 않으면 많이 아플 것입니다 ...


1

당신은 가까이 있습니다. 다음은 inode 번호로 파일을 삭제하는 방법입니다.

먼저을 사용하여 원하는 파일의 inode 번호를 찾으십시오 ls -li. inode 번호는 출력의 첫 번째 열에 있습니다.

예를 들면 다음과 같습니다.

$ls -li
311010 -rw-rw-r-- 1 me me 3995 Apr  6 16:27 -???\# ;-)

이 경우 inode 번호는 311010입니다.

findinode 번호로 파일을 찾는 데 사용하십시오 .

find . -inum 311010 

find삭제하려는 파일 이름 만 반환 해야합니다 . 예를 들면 다음과 같습니다.

$find . -inum 311010
./-???\# ;-)

당신이있게되면 find올바른 파일을 찾아 내고, 다음 통과 -delete에 매개 변수를 find. 파일이 삭제됩니다.

find . -inum 311010 -delete

0

다른 답변은 훌륭하며 거의 모든 환경에서 작동합니다.

그러나 GUI가 실행 중이면 노틸러스, 돌고래, konqueror 또는 좋아하는 파일 관리자에서 디렉토리를 열면 몇 번의 마우스 클릭으로 작동하지 않는 이름의 파일을 쉽게보고 삭제할 수 있어야합니다 .

일반 emacs 또는 vim 사용자가 아닌 경우 (몇 가지 다른 답변에 나와 있음) 가장 쉬운 방법 일 수 있습니다.


0

"\ 033"이라는 파일 (실제 "Escape"문자)과 비슷한 문제가있었습니다.

for x in $( ls | awk '!/^[A-Z]/ && !/^[a-z]/ && !/^[0-9]/');do rm -i -- $x ; done

위의 내용은 현재 디렉토리에서 문자 나 숫자로 시작하지 않는 파일을 제거하라는 메시지를 표시합니다.


0

대신, 현재 디렉토리의 이름을로 바꾸고, 이름을 DirX_OLD가진 새 디렉토리를 만들고 DirX모든 필요한 파일을에서 (으) DirX_OLD로 옮길 수 DirX있습니다. 파일을 복사 한 후 삭제할 수 있습니다DirX_OLD


0

누군가에게 도움이되는 경우를 대비하여 2 센트 가치를 추가 할 것입니다. 다음 stat과 같이 와일드 카드를 사용하여 파일 이름을 얻을 수있었습니다 .

stat -c %N *

산출:

`\220g\201\acontexts'
`\220g\201\alogins'
`\220g\201\amodules'
`\220g\201\apolicy'
`\220g\201\asetrans.conf'

그런 다음 ANSI C 인용 문자열 을 사용하여 파일에 액세스 할 수 있습니다.

rm $'\220g\201\asetrans.conf'

0

모든 파일에는 이름이 있으므로 정확히 어느 파일을 찾아야합니다.

이 파일을 예로 사용하겠습니다.

$ touch $'\177' $'\001\002' $'\033\027' a b abc $'a\177b'

해당 파일은 ?정상적으로 표시됩니다 ls.

$ ls
??  ?  ?002  a  abc  b

그러나 옵션을 ls허용 -Q하면 실제 파일 이름이 무엇인지 분명해야합니다.

$ ls -1iQ *
26739122 "\001\002"
26739117 "\033\027"
26739115 "\177"
26739118 "a"
26739121 "a\177b"
26739120 "abc"
26739119 "b"

이것들은 1pwd에있는 파일의 열에 있는 inode 번호와 "Quoted"이름입니다 .

확장 (글 로빙)을 사용하기 위해 (POSIX) 셸의 기능을 사용하고 있습니다.

비 인쇄 문자로 이름을 지정하려면 다음을 수행하십시오.

$ ls -1iQ *[![:print:]]*
26739122 "\001\002"
26739117 "\033\027"
26739115 "\177"
26739121 "a\177b"

비 인쇄 문자 만있는 파일을 나열하려면 다음을 수행하십시오 .

$ ls -1iQ [![:print:]]*
26739122 "\001\002"
26739117 "\033\027"
26739115 "\177"

그런 다음 선택적으로 ( -i대화식) 옵션을 제거하여 다음을 사용하십시오.

$ rm -i [![:print:]]*
rm: remove regular file ''$'\001\002'? n
rm: remove regular file ''$'\033\027'? n
rm: remove regular file ''$'\177'? n

y위 질문 에 대답 하여 지울 항목을 선택 하면됩니다.


0

자동 완성 기능이있는 bash가 있으면 효과가 있습니다. 디렉토리 목록에 표시된 문자를 입력했습니다. 그런 다음 자동 완성을 시작하고 인쇄 가능한 것으로 이름을 바꿨습니다.

다음은 나를 위해 일한 것입니다.

$ ll
-rw-r--r--.  1 xxxxxxxx  xxxxx 25608 Oct 11 11:11 ?
$ mv ?  
(hit the [tab] and it gets extended to ...)
$ mv ^[
(now complete the command and rename to something printable)
$ mv ^[ weirdchar
$ ll
-rw-r--r--.  1 xxxxxxxx  xxxxx 25608 Oct 11 11:11 weirdchar
(now delete)
$ rm weirdchar

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.