디렉토리에서 확장자가 pdf 인 파일을 제외한 모든 파일을 삭제하십시오.


50

다음을 포함하는 디렉토리가 있습니다.

x.pdf
y.zip
z.mp3
a.pdf

나는 떨어져 모든 파일을 삭제할 x.pdf하고 a.pdf. 터미널에서 어떻게해야합니까? 하위 디렉토리가 없으므로 재귀가 필요하지 않습니다.

답변:


63
cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
  • 첫 번째 명령은 파일을 삭제하려는 디렉토리로 이동합니다
  • 두 번째 명령은 .pdffilename으로 끝나는 파일을 제외한 모든 파일을 삭제합니다.

예를 들어, temp홈 폴더에 디렉토리가있는 경우 :

cd ~/temp

그런 다음 파일을 삭제하십시오.

find . -type f ! -iname "*.pdf" -delete

를 제외한 모든 파일이 삭제됩니다 xyz.pdf.

이 두 명령을 결합하여 다음을 수행 할 수 있습니다.

find ~/temp -type f ! -iname "*.pdf" -delete

.현재 디렉토리입니다. 끝에 !있는 파일을 제외한 모든 파일을 가져 오는 것을 의미합니다 .pdf. -type f디렉토리가 아닌 파일 만 선택합니다. -delete삭제하는 것을 의미합니다.

참고 :이 명령은 모든 하위 디렉토리뿐만 아니라 현재 디렉토리에있는 모든 파일 (pdf 파일은 제외하고 숨겨진 파일은 제외)을 삭제합니다. !전에 와야합니다 -name. 단순히 -name에만 포함됩니다 .pdf동안 -iname모두 포함 .pdf하고.PDF

하위 디렉토리가 아닌 현재 디렉토리에서만 삭제하려면 -maxdepth 1다음을 추가하십시오 .

find . -maxdepth 1 -type f ! -iname "*.pdf" -delete

답변 해주셔서 감사합니다. 구문을 조금 이해하도록 도와 줄 수 있습니까? ."and"를 의미합니까? !"제외" -name는 이름 매개 변수로 제외하려는 것을 의미 -delete하며 찾기시 수행해야하는 조치입니까? "* .pdf"를 제외한 모든 것을 찾아서 삭제합니까? 아니면 내가 잘못 이해 했습니까?
jessenorton

.현재 디렉토리를 의미합니다. 끝에 !있는 파일을 제외한 모든 파일을 가져 오는 것을 의미합니다 .pdf. -delete삭제하는 것을 의미합니다. 지금은 분명합니까?
Edward Torvalds

@terdon Starkers는 하위 디렉토리가 없다고 말했습니다. 대답을 더 광범위하게 편집하십시오
Edward Torvalds

+1 -maxdepth 1시작할 매개 변수를 포함해야합니다 . 그런 다음 재귀 적으로 삭제하려는 경우 매개 변수를 제거하는 것이 좋습니다.
Tulains Córdova

3
이것은-iname 대신에 사용해야 -name하거나 .PDF확장자가있는 파일 이 미끄러질 것이라는 점에 주목했습니다 .
muru December

43

bash'확장 된 쉘 대체 (globbing)을이야, 당신은 이외의 확장명을 가진 파일을 제거 할 수 .pdf사용

rm -- *.!(pdf)

@pts에서 언급했듯이 --문자는 명령 옵션의 끝을 나타내며 이름이 -문자로 시작하는 파일의 경우 드물게 명령을 안전하게 만듭니다 .

.pdf@DennisWilliamson이 지적한 것처럼 확장자가없는 파일과 확장자가 아닌 파일을 삭제하려면 다음을 사용할 수 있습니다

rm -- !(*.pdf)

확장 글 로빙은 기본적으로 사용하도록 설정되어 있지만 사용하지 않는 경우에는

shopt -s extglob

특히 스크립트 내에서 이것을 사용하려는 경우 표현식이 어떤 것과도 일치하지 않으면 (즉, 디렉토리에 pdf 파일이 아닌 파일이없는 경우) 기본적으로 glob가 확장되지 않은 상태로 전달됩니다. rm명령, 같은 오류가 발생

rm: cannot remove `*.!(pdf)': No such file or directory

nullglob쉘 옵션을 사용하여이 기본 동작을 수정할 수 있지만 자체 문제가 있습니다. 더 철저한 토론은 NullGlob-Greg 's Wiki를 참조하십시오.


더 나은 접근 방식 IMO.
Takkat December

확장자가없는 파일은 어떻습니까? FWIW, zsh에서rm *~*.pdf
Emil Jeřábek

1
괄호 안에 점을 넣을 것입니다.
Dennis Williamson

4
아, 별표도 안으로 들어가야 !(*.py)합니다. 또한 OP에서 ".pdf"파일 만 남길 원하는 경우 확장명이없는 파일도 삭제하고 무시해서는 안됩니다.
Dennis Williamson

1
이 접근법은 허용되는 답변보다 간단하고 깔끔합니다.
Peter

18

휴지통으로 삭제 :

$ cd <the directory you want>
$ gvfs-trash !(*.pdf)

또는 mv명령을 통해 (그러나 이런 방식으로 .trashinfo 정보를 기록하지 않기 때문에 휴지통에서 복원 할 수 없으므로 파일을 다음과 같은 대상 으로 이동했음을 의미합니다 ).

mv !(*.pdf) ~/.local/share/Trash/files

6
이 방법은 직접 사용하는 것보다 훨씬 안전 rm합니다.
세스

14

가장 쉬운 방법 : 어딘가에 다른 디렉토리를 작성하십시오 (재귀 적으로 하나의 디렉토리에서만 삭제하는 경우 하위 디렉토리 일 수도 있음). 모든 .pdf를 그곳으로 옮기십시오. 다른 모든 것을 삭제하십시오. PDF를 뒤로 이동하십시오. 중간 디렉토리를 삭제하십시오.

빠르고 쉬운 작업을 정확하게 볼 수 있습니다. 중간 디렉토리가 정리중인 디렉토리와 동일한 장치에 있는지 확인하여 이동이 사본이 아닌 이름을 바꿉니다!


4
+1 초보 사용자에게 의미가있는 설명을 다시 한 번 말하지만, 의도하지 않게 파일을 삭제하는 것은 거의 확실하지 않습니다.
trognanders

4

bash의 GLOBIGNORE를 사용하십시오 :

GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE

bash의 맨 페이지에서 :

글 로비 노어 :

            집합을 정의하는 콜론으로 구분 된 패턴 목록
            경로 이름 확장에 의해 무시 될 파일 이름.

빠른 테스트 :

mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *

산출:

y.zip
z.mp3

3

조심하고 작성 : xargs 사용

삭제하려는 파일 만 표시 한 다음를 rm사용하여 전송하는 방법을 작성하면 매우주의를 기울일 수 있기 때문에 내가 좋아하는 접근 방식이 있습니다 xargs. 예를 들면 다음과 같습니다.

  • ls 나에게 모든 것을 보여줘
  • ls | grep pdf보관하고 싶은 파일을 보여줍니다. 흠.
  • ls | grep -v pdf내가 지키고 싶은 것을 제외한 모든 것이 반대 입니다. 즉, 삭제하려는 항목의 목록이 표시됩니다. 위험한 일을하기 전에 이것을 확인할 수 있습니다.
  • ls | grep -v pdf | xargs rmrm삭제 를 위해 해당 목록을 정확하게 보냅니다.

내가 말했듯이, 나는 주로 그것이 제공하는 안전을 위해 이것을 좋아합니다 rm *. 다른 두 가지 장점 :

  • 작곡이 가능합니다. 당신은 사용할 수 있습니다 ls또는 find당신이 선호로, 초기 목록을 얻을 수 있습니다. 그 목록을 좁히는 과정에서 다른 것 grep, 다른 것 awk, 또는 무엇이든 원하는 것을 사용할 수 있습니다. 이름에 색상이 포함 된 파일 만 삭제해야한다면 같은 방식으로 만들 수 있습니다.
  • 각 도구를 주요 목적으로 사용할 수 있습니다. 나는 깃발 을 받아들이는 것을 기억 해야하는 것과 달리 find찾기와 rm제거 에 사용하는 것을 선호합니다 . 이 작업을 다시 수행하면 대체 솔루션을 작성할 수 있습니다. 대신에 파일을 휴지통으로 옮기고 ( "삭제 취소"대신) 파이프를 대신 하는 명령을 작성할 수 있습니다 . 해당 옵션 을 지원할 필요는 없으며 파이프로 연결하면됩니다.find-deletermtrashrmfind

최신 정보

파일 이름의 줄 바꿈, 파일 이름 등의 일부 경우를 처리하도록 수정하는 방법은 @pabouk의 주석을 참조하십시오 my_pdfs.zip.


4
여기서 세 가지 문제가 발견되었습니다. a)pdf 이름에 포함 된 파일은 제외합니다 . --- b) 접미사에있는 문자가 대문자이면 PDF 파일을 삭제합니다. --- c)의 출력을 사용하는 것은 좋지 않습니다 ls. 개행을 포함하는 파일 이름에는 작동하지 않습니다. ls특수 문자 를 대체하는 일부 구현 ( 예 : tab by) ?. --- 사용하는 것이 좋습니다 : find -maxdepth 1 -print0. (너무 짧게하지 ls: -----를 해결하려면)와 b)의 사용 grep -vi '\.pdf$': --- 전체 (그러나 GNU 전용) 솔루션find -maxdepth 1 -print0 | grep -viz '\.pdf$' | xargs -0 rm
pabouk

1
귀하는이 솔루션을 여러 번의 수동 반복이있는 "대화식"프로세스라는 의미로 이해했지만 긴 파일 목록에는이 검사를 거의 사용할 수 없으며 위에서 언급 한 문제로 인해 실수를 간과하기 쉽습니다.
pabouk

1
@pabouk 좋은 포인트; 현실 세계는 항상 사물을 복잡하게 만들고 수정 사항이 도움이됩니다. :) 그러나 나는 여전히이 전반적인 접근법이 최선이라고 생각합니다. 모든 것을 시각적으로 확인할 수있는 파일이 너무 많으면 | head -20적어도 그것이 대략적 으로 보이는지 알 수 있지만, 그렇지 않으면 rm my_pattern큰 실수를 발견 할 기회가 없습니다.
Nathan Long

1
파일을 삭제하기 전에 파일을 표시하고 -delete를 생략하고 find . -type f ! -name "*.pdf"콘솔로 인쇄하거나 파일을 적거나 적은 파일로 파이프하는 데 사용할 수 있습니다. [그리고 pabouk의 주석처럼 원한다면 xargs로 rm으로 파이프 (이상한 파일 이름의 경우 -print0 | ... -0로)]
Xen2050

3

나는 일반적으로 대화 형 파이썬 인터프리터에서 이러한 문제를 해결합니다.

mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
...   if not f.endswith('.pdf'):
...     os.remove(f)

그것은과 한 줄 이상 수 있습니다 find또는 xargs, 그러나 먼저 조회하지 않고, 그것은 매우 탄력, 그리고 내가 무슨 일을하는지 정확히 알지.


모든 추가 라인에 점점 긴장하는 사람들을 위해, 우리 그것을 하나의 라인으로 만들 수 있습니다 :for item in [f for f in os.listdir('.') if not f.endswith('.pdf')]: os.remove(item)
Jacob Vlijm

python -c "import os; for f in os.listdir('.'): if not f.endswith('.pdf'): os.remove(f)"
mic_e

[os.remove(f) for f in os.listdir('.') if not f.endswith('.pdf')]
mic_e

좋은! 두 번째는 구문 오류를 발생시킵니다. 이유를 모르겠습니다.
Jacob Vlijm

이상한; 내 시스템에서 python 3.4 및 python 2.7 모두에서 작동합니다.
mic_e

2

이 질문에 대한 더 나은 답변 (이전 답변과 비교)은 강력한 file명령 을 사용하는 것 입니다.

$ file -i abc.pdf
abc: application/pdf; charset=binary

이제 당신의 문제 :

cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done

for명령 작업은 현재 디렉토리의 파일을 variable 형식으로 제공합니다 $var. if-then명령은 0from file -i "$var" | grep -q 'application/pdf\;'명령 의 종료 상태를 가져 와서 pdf 파일의 이름을 출력하며 pdf 파일을 0찾은 경우에만 종료 상태를 제공 합니다.


1
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')

경고! 더 나은 시도 먼저

ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')

2
어, 이것은 smallo.ruhr.de/award.html#ls , smallo.ruhr.de/award.html#grep 와 같은 여러 가지 방법으로 결함이 있으며 공백이나 특수 문자가있는 파일 이름은 완전히 무시합니다.
David Foerster

1
대소 문자를 구분하지 않는 일치 -i와 함께 사용해야합니다 grep.
muru December

1
rm -i -- !(*@(a|x).pdf)

로 읽 a.pdf거나 아닌 파일을 모두 제거하십시오 x.pdf.

이 2 확장 globs와 이용하여 작동, 외부는 !()자체가 작은 방울 중 하나 이상 일치해야 필요 포함 된 글로브 부정 a또는 x전과 패턴 .pdf접미사. glob # extglob를 참조하십시오 .

$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

$ echo -- !(a.pdf)
-- x.pdf y.zip z.mp3

$ echo -- !(x.pdf)
-- a.pdf y.zip z.mp3

$ echo -- !(a.pdf|x.pdf)
-- y.zip z.mp3

$ echo -- !(@(a|x).pdf)   # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.zip z.mp3

$ echo -- !(*@(a|x).pdf)  # but this doesn't
-- y.zip z.mp3

$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.zip z.mp3

1

휴대용 쉘 방식

$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'

어떤 Bourne의 스타일 쉘 거의 POSIX 호환 ( ksh, bash, dash). 휴대용 스크립트 및 bash확장 쉘 글 로빙을 사용할 수없는 경우에 적합합니다 .

펄 :

$ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             

또는 약간 더 깨끗합니다 :

$ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'

대체 파이썬

python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'

0

삭제하는 내용에주의하십시오!

ls포착되지 않은 동작으로 인해 원치 않는 파일이 삭제 될 수 있으므로 삭제하기 전에 먼저 테스트하는 것이 안전 합니다. 디렉토리 외부에서 직접 수행 할 수 있습니다. ls와 비슷합니다 rm.

ls sub/path/to/files/!(*.pdf)

이것은 나열됩니다

y.zip
z.mp3

이제 삭제중인 내용을보고 안전하게 삭제할 수 있습니다.

rm sub/path/to/files/!(*.pdf)

그리고 그게 다야. *프로그래밍 과정 문서 만 유지하는 것처럼 와일드 카드 를 사용 하여보다 선택적으로 사용할 수 있습니다 .

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