rm이 제거 할 파일을 항상 나열합니까?


33

뭔가 내가 확실히 알아야 할 기분이 : 나는 경우 ls <something>, 것입니다 rm <something>정확히 같은 파일 제거 ls표시를? 표시되지 않은 rm파일을 제거 할 수 있는 상황이 ls있습니까? (이것은 18.04 bash에 있습니다)

편집 : 답변 한 모든 사람에게 감사합니다. 나는 정답이 모든 답의 조합이라고 생각합니다. 그래서 가장 많이 투표 된 답을 "답변"으로 받아 들였습니다.

내가 그 과정에서 배운 예기치 않은 것들 :

  • ls 논쟁을 다룰 때 생각하는 것만 큼 간단하지 않습니다.
  • 우분투 설치와 함께 간단한 비 바이올린, .bashrc 별칭 ls
  • 명령 인수처럼 보일 수있는 대시로 시작하는 파일 이름을 지정하지 마십시오. 이름을 -r로 지정하는 것이 좋습니다!

8
나는 깃발 rm이없는 것이 다소 놀랐다 --dry-run.
fkraiem

20
@Rinzwind 왜 find -delete보다 rm좋을까요? 당신은 "그 이유입니다"라고 말하지만 그것이 무엇을 의미하는지는 완전히 명확하지 않습니다. 또한 find호출하면 현재 디렉토리의 모든 파일이 재귀 적 으로 rm삭제되며 바로 디렉토리의 파일 만 삭제됩니다. 또한 -name *no-op입니다. 대체로, 나는 당신의 조언에 의아해합니다 ...
marcelm

3
@marcelm 나는 그것을 사용하는 find것이 당신이 그것을 실행할 수 있고, 모든 파일을보고, 같은 명령을 실행하기 때문에 조언이라고 생각합니다 -delete. 의 결과를 이미 보았으므로 find제거 할 대상에 대한 모호성이 없어야합니다 (실제로 이에 대한 자세한 내용을 답변 형태로 듣고 싶습니다)
Scribblemacher

5
@Scribblemacher "... 당신은 모든 파일을 볼 실행할 수 있습니다, 다음과 같은 명령을 실행 -delete" -하지만 어떻게 더 잘 실행보다 ls <filespec>뒤에 rm <filespec>(영업 이익이 이미 수행하는 방법을 알고있는)?
marcelm

12
@Rinzwind "이것은 ls 이후 및 rm 이전에 파일이 생성되는 순간에 대한 choroba의 답변을 해결합니다." -아뇨. 당신이 실행하는 경우 find ... -print확인하려면 먼저 파일을 삭제하는 것, 그리고 무엇을 find ... -delete, 당신은 두 개의 명령 사이에 여전히 삭제 파일을 생성합니다. 당신이 모두를 사용하는 경우 -print-delete, 당신은, 삭제 된 내용의 단지 사후 보고서를 확인하지 않습니다 (당신은 사용뿐만 아니라 수도 rm -v).
marcelm

답변:


40

음, 모두 lsrm그들에게 전달되는 인자에서 작동합니다.

이러한 주장은 그래서 간단한 파일 일 수 있습니다 ls file.extrm file.ext같은 파일에 작동하고 결과는 분명하다 (목록 파일 / 파일을 삭제).

대신 인수가 디렉토리 일 경우, ls directory목록 의 콘텐츠 동안 디렉토리 rm directory로 작동하지 않습니다이다 (즉, rm당신이 경우에 동안 플래그없이이 디렉토리를 제거 할 수 없습니다 rm -r directory, 그것은 반복적으로 삭제 된 모든 파일 에서 directory 와 디렉토리 자체 ).

그러나 명령 행 인수는 쉘 확장에 종속 될 수 있으므로 와일드 카드, 변수, 다른 명령의 출력 등이 포함 된 경우 동일한 인수가 두 명령 모두에 항상 전달되는 것은 아닙니다 .

극단적 인 예로 생각 ls $(rand).txt하고 rm $(rand).txt, 논쟁은 "동일"하지만 결과는 상당히 다릅니다!


3
또한 "숨겨진"(도트) 파일이있는 lsvs를 고려하십시오 . 그러나 그 자체로는 의미가 없으므로 전체가 사과와 오렌지입니다. 내가 올바르게 이해했다면, 그것은 당신의 대답의 요점입니다. 정말 잘했습니다 :)rm *ls *rm
Monica와 Lightness Races

5
또 다른 의견 lsrm -r명령 : ls <directory>디렉토리 내의 숨겨진 파일이 표시되지 않습니다,하지만 rm -r <directory> 조차 숨겨진 파일을 삭제합니다.
Daniel Wagner

1
@LightnessRacesinOrbit ls는 (로 별칭이 지정되지 않은 한) 나열하지 않으며 (설정하지 않은 한 ls -a) rm *삭제하지 않습니다 dotglob.
모닝 그만 모니카

20

ls foo*.txtvs 와 같은 것을 생각하고 있다면 rm foo*.txt예, 동일한 파일을 표시하고 제거합니다. 쉘은 glob를 확장하여 해당 명령으로 전달하고 명령은 나열된 파일에서 작동합니다. 하나는 그들을 나열하고 하나는 제거합니다.

명백한 차이점은 해당 파일 중 하나가 디렉토리 인 경우 ls해당 내용을 나열하지만 rm제거하지 못하는 것입니다. 에 표시된 것보다 적은 것을 rm제거 하므로 일반적으로 문제가되지 않습니다 .ls

여기서 큰 문제는 실행 중이 ls *거나 대시로 시작rm * 하는 파일 이름이 포함 된 디렉토리에서 발생합니다 . 그들은 당신이 직접 그들을 쓴 것처럼 두 프로그램의 명령 줄에 확장 것이고, ls걸릴 것이라고 -r하면서, "역 정렬 순서"를 의미하는 rm걸릴 -r재귀 제거를 의미 할 수 있습니다. 하위 디렉토리가 두 레벨 이상인 경우 차이점이 중요합니다. ( ls *첫 번째 레벨 디렉토리의 내용을 표시하지만 rm -r *첫 번째 하위 레벨 이후의 모든 항목도 표시됩니다.)

이를 방지하기 위해 ./현재 디렉토리를 나타내는 선행 글로 글로브를 작성 하거나 --글로브 전에 옵션 처리의 끝 을 알리기 위해 (예 : rm ./*또는 rm -- *)를 넣으십시오 .

와 같은 glob를 사용하면 *.txt점이 잘못된 옵션 문자이므로 실제로 문제가되지 않으며 오류가 발생합니다 (누군가가 유틸리티를 확장하여 의미를 발명 할 때까지). 그러나 ./어쨌든 거기 에 두는 것이 더 안전 합니다.


물론 쉘의 글 로빙 옵션을 변경하거나 명령 사이에서 파일을 생성 / 이동 / 제거하면 두 명령에 대해 다른 결과를 얻을 수도 있지만 이러한 경우를 의심합니다. (신규 / 이동 한 파일을 처리하는 것은 안전하게 수행하기가 매우 어려울 수 있습니다.)


1
고맙습니다. 이것은 전체 명령 줄 구문의 문제를 강조하는 것 같습니다. 대시로 시작하는 파일의 이름을 지정하면 위험한 물에서 항해하고 있습니다. -파일에 대해 잊어 버린 후, 앞으로 어떤 명령을 사용할지 누가 알겠습니까?
B.Tanner

1
@ B.Tanner입니다. 어떤 의미에서 문제는 명령 행 인수가 단순한 문자열이라는 것입니다. 시스템이 오늘날 설계 되었다면, 실행 된 프로그램이 인수가 옵션 플래그인지 여부를 알 수 있도록 더 많은 구조가있을 수 있습니다. 파일 이름의 매우 느슨한 구조에서 오는 다른 문제도 있습니다. dwheeler의해 매우 철저한 에세이가 있지만 그것을 읽는 것이 상처를 입을 것이라고 경고해야합니다. (세부 사항이나 잘못 될 수있는 것의 철저한 끔찍함에서).
ilkkachu

3
나는 저항 할 수 없다, 당신은 나에게 그것을 팔았고, 나는 지금 그것을 읽을 것이다. 나는 많은 파일 이름 끝에 캐리지 리턴 문자를 얻을 수 있었던 시간의 기억과 함께 나는 그 사람이 오는 것을 볼하지 않았다 ... 또한 bash는 스크립트로 실행할 수있는 Windows 배치 파일을 생성)!
B.Tanner

17

쉘 동작을 제쳐두고, 자신 rmls처리 할 수 있는 것에 만 초점을 맞 춥니 다 . 적어도 하나의 경우 ls무엇을 보여줄 것이다 rm특별한 디렉토리 - 제거 할 수 없습니다 디렉토리 권한 및 다른 관련 .과를 ...

폴더 권한

rm파일을 제거하면 디렉토리 내용이 변경되기 때문에 디렉토리에 대한 작업입니다 (즉, 디렉토리 항목 목록은 디렉토리 가 파일 이름 및 inode 목록에 불과하기 때문입니다 ). 즉, 디렉토리에 대한 쓰기 권한이 필요합니다. 파일 소유자 인 경우에도 디렉토리 권한이 없으면 파일을 제거 할 수 없습니다. 반대의 경우도 마찬가지입니다 : rm당신이 디렉토리 소유자 인 경우, 다른 사람이 소유 할 수있는 파일을 제거 할 수 있습니다.

따라서 디렉토리에 대한 읽기 및 실행 권한이있을 수 있습니다. 예를 들어 ls /bin/echo, 디렉토리를 순회하고 내용을 잘 볼 수는 있지만, 권한을 rm /bin/echo소유 /bin하거나로 권한을 부여 하지 않는 한 할 수 없습니다 sudo.

그리고 당신은 어디에서나 이와 같은 경우를 볼 수 있습니다. https://superuser.com/a/331124/418028 와 같은 경우가 있습니다.


특수 디렉토리 '.' 그리고 '..'

또 다른 특별한 경우는 ...디렉토리입니다. 당신이 할 경우 ls .또는 ls .., 그것은 행복하게 당신에게 내용을 보여 주지만 것이다 rm그들이 허용되지 않습니다 보내고 '

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

15

입력 ls *한 다음 표시된 rm *것보다 많은 파일을 제거 할 수 있습니다. 파일 ls의 끝 ls과 시작 사이의 작은 시간 간격으로 생성되었을 수 있습니다 rm.


1
이는 /tmp많은 응용 프로그램이 임시 파일을 생성 할 수 있는 가능성있는 사례 이므로 항상 두 명령 모두에서 가능합니다 *. 그러나 일부 응용 프로그램은 unlink()파일 핸들을 열어 둔 상태에서 파일을 익명으로 만들어 파일을 표시 할 수는 ls *있지만 rm *이를 잡을 수는 없습니다.
Sergiy Kolodyazhnyy

1
@OrangeDog 요점을 놓쳤다. 우리는 경쟁 조건에 대해 이야기하고 있습니다
Sergiy Kolodyazhnyy

1
@OrangeDog 지금 전화 중이기 때문에 이것을 확인해야하지만 디렉토리 내용 목록이 바뀌었기 때문에 표시 내용과 작동 *내용 ls이 다르 더라도 요점은 여전히 존재 rm합니다.
Sergiy Kolodyazhnyy

1
하나의 명령 만 수행하더라도 인수를 확장 한 다음 삭제하는 경쟁 조건이 있습니다.
중지 해 모니카

1
@OrangeDog 나는 그것에 동의 할 수 있습니다. 와일드 카드 확장은 기존 파일 이름에서 작동하므로 예, 와일드 카드 확장 쉘과이를 처리하는 명령간에 경쟁 조건이 있으므로 ls *실제로 사라진 파일 이름을 실제로 표시 할 수 있습니다.
Sergiy Kolodyazhnyy

9

ls *그리고 rm *글로브를 확장 할 책임이 없습니다-이것은 명령으로 전달하기 전에 쉘에 의해 수행됩니다.

즉 , 확장 된 파일 목록과 함께 모든 명령을 사용할 수 있으므로 가능한 적은 작업을 사용합니다.

따라서이 작업을 수행하는 더 좋은 방법 (또는 적어도 다른 방법)은 중개인을 건너 뛰는 것입니다.

echo *rm명령에 전달 될 내용을 정확하게 보여줍니다 .


2
이 시나리오에서 ls 대신 echo를 사용하는 아이디어가 마음에 듭니다.
B.Tanner

3
또는 printf "%s\n" *공백이있는 파일 이름을 명확하게 볼 수 있습니다. (또는 %q그 대신에 더
못생긴

4

어때요 :

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

./-r:

기본적으로 와일드 카드로 시작 물건에 확대 -(또는 수동으로 입력 물건을 시작으로 -좀 더 부정 행위처럼 보이지만 있음)에 의해 다르게 해석 될 수 lsrm.


4

보여지는 것이 제거되는 것이 아닌 경우 가 있습니다 . 전달하는 인수가 디렉토리에 대한 심볼릭 링크 인 경우 다소 극단적이지만 운 좋게도 하나는 심볼릭 링크 된 디렉토리의 모든 파일을 표시 하고 심볼릭 링크는 제거하고 원래 디렉토리와 그 내용은 그대로 유지 한 상태입니다.lsrmlsrm

% ln -s $HOME some_link
% ls some_link    # Will display directory contents  
bin    lib    Desktop ...
% rm some_link
% ls $HOME
bin    lib    Desktop ...

1
허. 나를 위해 ln -s $HOME some_link; ls some_link출력 some_link@하지만에 ls별칭이 ls -F있습니다. 분명히, -F링크를 비 참조하는 대신 링크를 표시하도록 동작을 변경합니다. 기대하지 않았다.
marcelm

과연! 또한 ls -l예를 들어 대상이 아닌 링크를 대상으로합니다. 링크 자체를 검사하는 방법이 있어야합니다.
Alexis

1
질문에 옵션을 추가하면 너무 많은 열어 possibilities-- 내 대답은 수정되지 않은의 행동에 관한 것입니다 lsrm.
Alexis

당신이 말한다면 ls some_link/,  ls -H some_link또는 ls -L some_link, 그것은이 연결된에 디렉토리에 추가하는 경우에도 나열됩니다 -F-l. 반대로 (정렬) -d디렉토리의 내용보다는 디렉토리를 보라고 말합니다. ls -l /tmp와 비교하십시오 ls -ld /tmp.
G-Man, 'Reinstate

물론의 동작을 변경하는 플래그를 추가 할 수 있습니다 ls. 당신은 기본적으로 왜 다른 플래그로 행동을 열거하는
것이이

4

만 할 경우 ls대신 ls -a, 그래 rm당신이 보지 못한 숨겨진 파일을 제거 할 수 ls없는가 -a.

예 :

에 따르면 :

dir_test
├── .test
└── test2

ls dir_test : test2 만 표시합니다

ls -A dir_test : test2 + .test를 표시합니다

rm -r dir_test : 모두 제거합니다 (.test + test2)

도움이 되길 바랍니다.


예를 들어 줄 수 있습니까? 일반적으로 rm *도트 파일을 제거하지 않습니다. 만약 그렇다면, ls *그것들도 보여줄 것입니다.
marcelm

아니요, ls *숨겨진 파일은 표시하지 않습니다.
DevHugo

그러나 예, 약간 혼란 스럽습니다. 예제를 추가했습니다.
DevHugo

1
ls -a나열합니다 ., .., .testtest2. 당신은 사용에 예를 변경할 수 있습니다 ls -A, 어떤 목록 모든 것을 제외 . 하고 ..(즉, 만 .test등을 test2).
G-Man, 'Reinstate

3

이미 많은 좋은 답변이 있지만 더 깊은 통찰력을 추가하고 싶습니다.

스스로에게 질문하십시오 : ls당신이 쓰면 얼마나 많은 매개 변수가 전달됩니까?

ls *

...? 점을 유의 ls명령을하지 않는 *모든 파일이있는 경우 매개 변수로 *확장 할 수는. 대신, 쉘은 명령을 호출하기 전에 먼저 글 로빙을 수행하므로 ls명령은 실제로 글 로빙과 일치하는 파일 수만큼 많은 매개 변수를 가져옵니다. 글 로빙을 억제하려면 매개 변수를 인용하십시오.

이 모든 명령 마찬가지입니다 : echo *echo '*'.

스크립트가 있습니다 countparams.sh. 효과를 테스트 하기 위해 호출하십시오 . 전달 된 매개 변수 수를 알려주고 나열합니다.

#!/bin/bash
echo "This script was given $# parameters."
arr=( "$@" )
for ((i=0;i<$#;i++)); do
        echo "Parameter $((i+1)): ${arr[$i]}"
done

실행 가능하게 만들고 실행하십시오 ./countparams.sh *. 출력에서 배우십시오!


1

디렉토리 내용이 서로 다른 두 시간에 동일한 경우 글로브는 같은 방식으로 두 번 확장됩니다 .


제거 할 대상을 실제로 확인하려면을 사용하십시오 rm -i *.txt. 제거하기 전에 각 파일에 대해 별도로 프롬프트를 표시합니다.

이것은 경쟁 조건에 대한 안전 보장 :
        ls *.txt/ 새 파일이 생성 / rm *.txt
당신은 제거를하고있어 같은 프로그램에 의한 모든 파일에 대해 묻는 메시지가 있기 때문이다.


이것은 정상적인 사용에는 너무 번거롭고에 대한 별칭 rmrm -i사용하면 자주 사용 \rm하거나 rm -f자주 사용 하게됩니다. 그러나 경쟁 조건에 대한 해결책이 있다는 것은 적어도 언급 할 가치가 있습니다. (GNU 이외의 시스템에도 이식 가능합니다. POSIX rm(1)-i옵션을 지정합니다 .)

다른 옵션은 bash 배열입니다 : to_remove=(*.txt), 그런 다음 사용자에게 확인을 요청하십시오 (아마도 ls -ld -- "${to_remove[@]}") 후 rm -- "${to_remove[@]}". 따라서 glob 확장은 한 번만 수행되며 목록은 그대로 전달됩니다 rm.

실제로 사용할 수있는 또 다른 옵션은 GNU rm -I( man page )이며, 항목을 4 개 이상 제거 할 경우 프롬프트됩니다. (하지만 전체 목록 만 표시하지는 않습니다.) alias rm='rm -I'데스크탑에서 사용 합니다.

너무 많이 일치하는 반 유형 패턴으로 팻 핑거링 리턴에 대해 좋은 보호 책입니다. 그러나 lsfirst를 사용하는 것은 일반적으로 사용자가 소유 한 디렉토리 나 단일 사용자 시스템에서, 그리고 비동기 적으로 새 파일을 작성할 수있는 백그라운드 프로세스가없는 경우에 좋습니다. 지방질을 막으려면 rm -rf /foo/bar/baz왼쪽에서 오른쪽으로 입력하지 마십시오 . rm -rf /특별한 경우이지만 rm -rf /usr그렇지 않습니다! 밖으로 남겨 -rf부분, 또는 시작 ls, 만 추가 rm -rf경로를 입력 한 후 부분.

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