터미널에서 하나의 파일을 제외한 특정 확장자를 가진 파일 제거 파일을 제거해야합니다. 터미널 에서이

이름이 “filename.gif”인 파일 하나를 제외하고 확장자가 .gif 인 모든 파일을 제거해야합니다. 터미널 에서이 작업을 수행하는 가장 좋은 방법은 무엇입니까?

rm 명령 *.gif은 파일을 포함하여 모든 gif 파일을 제거합니다 filename.gif.



답변

사용해야 할 간단한 솔루션은 다음과 같습니다.

mv filename.gif filename.gif.keep
rm *.gif
mv filename.gif.keep filename.gif

.keep확장명에는 특별한 것이 없습니다 .gif. 파일 이름이 일시적으로 끝나지 않도록 확장 합니다.

파일 이름을 변경하지 않아야하는 경우 (그리고 이것이 중요한 스크립팅 상황이있는 경우) :

for X in *.gif; do
    if [ "$X" != "filename.gif" ]; then
        rm "$X"
    fi
done

또는 다음과 같이 더 짧게 작성할 수 있습니다.

for X in *.gif; do [ "$X" != "filename.gif" ] && rm "$X"; done

find대신 사용하는 것이 좋습니다. 매우 강력한, 당신은 할 수 더 읽기 고려하고, 더 나은 핸들 과 같은 문자가 이상한 파일 이름 *그들 .

find . -maxdepth 1 -not -name 'filename.gif' -name '*.gif' -delete

나는 -not가독성을 위해 연산자를 사용 했지만, GNU find를 사용하지 않거나 다른 스크립트로 배포하거나 다른 시스템에서 실행하려는 경우 POSIX 준수가 중요한 경우에는 !대신 연산자를 사용하십시오 .

find . -maxdepth 1 ! -name 'filename.gif' -name '*.gif' -delete

한 가지 편리한 점은 find대소 문자를 구분하지 않는 명령을 쉽게 수정할 수 있으므로 확장자가있는 파일도 찾아서 삭제할 수 있다는 것입니다 .GIF.

find . -maxdepth 1 -not -name 'filename.gif' -iname '*.gif' -delete

검색 패턴 -iname대신 사용 했지만에 사용 하지 않았습니다 . 아마도 파일이 무엇인지 정확히 알고 확장명 뿐만 아니라 파일 이름의 다른 곳에서도 대체 대문자와 일치 합니다.-name*.giffilename.gif-iname

이러한 모든 솔루션 은 현재 디렉토리에있는 파일 만 삭제합니다 . 현재 디렉토리에 포함되지 않은 파일은 삭제하지 않으며 현재 디렉토리의 하위 디렉토리에있는 파일은 삭제하지 않습니다.

현재 디렉토리 내에 포함 된 모든 파일을 삭제하려면 (즉, 서브 디렉토리 및 해당 서브 디렉토리의 서브 디렉토리 등을 포함하여) 현재 디렉토리 또는 그 하위 디렉토리에 포함 된 파일을 삭제하려면 다음을 사용 find 하지 않고 사용하십시오 maxdepth -1.

find . -not -name 'filename.gif' -name '*.gif' -delete

이것에 조심하십시오!

로 다른 값을 설정할 수도 있습니다 -maxdepth. 예를 들어, 현재 디렉토리와 그 하위 및 손자에서 파일을 삭제하지만 더 깊은 것은 아닙니다.

find . -maxdepth 3 -not -name 'filename.gif' -name '*.gif' -delete

-delete다른 표현을하기 전에 절대로 먼저 두지 마십시오 ! 당신은 내가 항상 -delete끝에 놓인 것을 볼 수 있습니다. 처음에 넣으면 먼저 평가되고 아래의 모든 파일 .(끝없는 .gif파일과 깊은 하위 하위 디렉토리의 파일 포함 .)이 삭제됩니다!

자세한 내용은 대한 매뉴얼 페이지를 참조 bash하고 sh이러한 예에서 사용되는 명령에 대한이 : mv, rm, [,와 (특히) find.


답변

당신이 사용하는 경우 bash(기본 쉘)는 extglob쉘 옵션을 사용하면 확장 된 패턴 일치 구문을 사용할 수 있습니다. 이를 활성화하려면 shopt내장 명령을 사용하십시오 .

shopt -s extglob

( .bashrc파일에 해당 줄을 포함 시킵니다.)

무엇보다도, 그것은 !()연산자에 대한 액세스 권한을 부여하며 , 이는 연산자 안에 있지 않은 패턴과 일치합니다. 당신의 목적을 위해 :

rm !(filename).gif

자세한 내용은 man bash“패턴 일치” 에서 확인할 수 있습니다 .


답변

+ + 로 터미널 을 열고 다음을 입력하십시오.CtrlAltT

find . -type f -name "*.gif" -and -not -name "filename.gif" -exec rm -vf {} \;

의 차이 -delete와는 -exec rm -vf {} \;두 번째 옵션과 함께, 당신은 때문에의 파일이 제거 된 볼 수있을 것입니다 -v플래그. -delete옵션 으로는 할 수없는 일입니다 . ( -name -delete파일 이름을 인쇄 할 것이지만 rm으로는 -v각 파일의 경우 보여준다 성공적 으로 삭제되었습니다.)


답변

있다 GLOBIGNORE변수. 보낸 사람 man bash:

GLOBIGNORE
      A colon-separated list of patterns defining the set of filenames
      to be ignored by pathname expansion.  If a filename matched by a
      pathname expansion pattern also matches one of the  patterns  in
      GLOBIGNORE, it is removed from the list of matches.

따라서 간단한 방법은 GLOBGINORE문제의 파일 이름으로 설정 하는 것입니다.

$ touch {a,b,c,d}.png
$ echo *.png
a.png b.png c.png d.png
$ GLOBIGNORE=c.png
$ echo *.png
a.png b.png d.png

따라서 귀하의 경우 :

GLOBIGNORE=filename.gif; rm *.gif

물론 GLOBIGNORE패턴이 포함되어 있으므로 패턴을 제외 할 때마다 사용할 수 있습니다.

$ GLOBIGNORE='[a-c].png'; echo *.png
d.png
$ touch bd.png; GLOBIGNORE='?.png'; echo *.png
bd.png

장점 (?!)은 자동으로 제외 하고 일치하지 않도록 GLOBIGNORE설정 하면 다음 을 가능하게합니다 ....dotglob

The  GLOBIGNORE shell variable may be used to restrict the set of file‐
names matching a pattern.  If GLOBIGNORE is set, each matching filename
that also matches one of the patterns in GLOBIGNORE is removed from the
list of matches.  The filenames ``.''  and ``..''  are  always  ignored
when  GLOBIGNORE is set and not null.  However, setting GLOBIGNORE to a
non-null value has the effect of enabling the dotglob shell option,  so
all other filenames beginning with a ``.''  will match.  To get the old
behavior of ignoring filenames beginning with a ``.'', make ``.*''  one
of  the  patterns  in  GLOBIGNORE.  The dotglob option is disabled when
GLOBIGNORE is unset.

따라서 디렉토리의 모든 파일과 폴더 를 삭제하는 간단한 방법은 다음 과 같습니다.

GLOBIGNORE=.; rm -r *

이 활성화 된 이후로 *시작하는 파일 이름과 일치 하지만 또는 일치 하지 않으므로 부모 디렉토리에는 영향을 미치지 않습니다..GLOBIGNOREdotglob...