특정 파일 이름과 일치하지 않는 파일을 삭제하는 스크립트

특정 파일 이름과 일치하지 않는 파일을 삭제하는 스크립트

연도와 월별로 하위 폴더로 정렬된 500,000개의 이미지가 있는 폴더가 있습니다. 이 작업을 수행하는 스크립트를 만들고 싶습니다.

파일 이름인 경우확실히파일 이름을 일치시키고 names.log파일을 삭제하십시오. names.log파일 이름이 포함됩니다. 예:

image1.jpg
photo3.jpg
redcar.jpg
balloon2323.jpg

잠깐... 보관하고 싶은 파일 이름이 10,000개 정도 있어요

내 서버에 PHP와 Python이 있지만 이에 가장 적합한 것이 무엇인지 잘 모르겠습니다. 나는 이전에 어떤 스크립트도 작성하지 않았습니다. 누군가 이 작업을 수행하는 코드 조각을 제공하고 이를 실행하는 방법을 알려줄 수 있습니까? 아니면 명령을 통해 달성할 수 있습니까?

답변1

이것은 Python에서는 매우 간단합니다.os.walk. 경고, 테스트되지 않은 코드입니다. 이름 목록에는 행당 하나의 이름이 포함되어 있다고 가정합니다.

#!/usr/bin/python2
import os
names_file = open('names.log')
names = set(line.rstrip('\n') for line in names_file.readlines())
names_file.close()
for root, dirs, files in os.walk('/path/to/top/directory'):
    for name in files:
        path = os.path.join(root, name)
        if os.path.isfile(path):
            if name not in names:
                print path
                #os.remove(path) # uncomment this line if you're happy with the set of files to remove

답변2

find -name '*.jpg' -print0 | grep -zZ -vf name.log | xargs -0 COMMAND

원하시면 교체 COMMAND하세요ls -lrm

편집하다: 제공된 명령은 name.log를 정규식 집합으로 처리합니다. @terdon name.log는 파일 이름 목록임을 기억하세요.

파일 이름이 일반적인 "일반" 문자를 사용하는 경우에는 충분할 수 있지만 다음과 같은 경우에는 문제가 발생할 수 있습니다.

  1. 파일 이름/정규식에는 등의 특이한 문자가 포함되어 있습니다 [. ](이 경우 일부 파일 삭제가 실패할 수 있으며 이름이 지정된 일부 파일이 삭제될 수도 있습니다 name.log!) 이를 방지하려면 grep -F에 특수 문자를 사용하거나 보호 할 수 있습니다 name.log.
  2. 정규식은 파일 이름의 하위 문자열과 일치합니다(이 경우 일부 파일은 삭제되지 않습니다. a.jpg"a"로 끝나는 모든 이미지와 일치합니다(예: camera.jpg, banana.jpg).

사례 2의 경우 접두사 사례의 경우 -- 정규식 시작 부분에 "/"를 추가할 수 있습니다.

sed 's!^!/!'  name.log > new.log
find -name '*.jpg' -print0 | grep -F -zZ -vf new.log | xargs -0 COMMAND

심지어

find -name '*.jpg' -print0 | grep -zZFvf <(sed 's!^!/!' name.log) | xargs COMMAND

사례 2의 경우 이미지 파일에 확장자가 있으므로 접미사 사례는 덜 중요합니다. 이 상황을 올바르게 해결하려면 "파일 이름 뒤에는 아무것도 없습니다"라고 말해야 합니다. 정규식이 필요하고 . [ ]파일 이름의 특수 문자( example )를 보호해야 합니다.

sed -re 's!([].[])!\\\1!g; s!.*!/&$!' name.log > new.log
find -name '*.jpg' -print0 | grep -zZ -vf new.log | xargs -0 COMMAND

답변3

이것은진짜.pax-s작성하는 동안 파일 이름을 변경하는 대체 옵션의 개념이 있습니다 . -s여러 대체 매개변수를 지정할 수도 있습니다 . 그리고 여기서 가장 관련성이 높은 것은 선택한 멤버가 -s성공적인 일치에 필요한 대체 매개변수만 적용하지만 파일 이름이 비어 있는 대체 항목으로 인해 일치하는 파일이 선택되지 않는다는 것입니다.

전시하다:

mkdir test; cd test
touch match nomatch
pax -ws '|^.*/match$|&|' -s '|.*||' ./ |
pax -v

위의 코드는 ./test디렉토리를 생성 및 변경하고 두 개의 파일을 생성한 다음 파이프에 아카이브를 씁니다. -w여기서 두 번째 파일은 파이프의 내용을 자세히 설명합니다 . 위의 내용은 다음과 같습니다.tarpaxpax -v

-rw-r--r-- 1 mikeserv mikeserv 0 Feb 22 11:40 ./

... ./match일치하니까앞으로최종 대체는 파일 이름의 모든 문자를 대체합니다.

그리고 pax실제로 파일 내용을 해당 아카이브에 복사할 필요가 없습니다. -rwl하드 링크를 생성하는 복사 작업을 사용할 수 있습니다.

따라서 파일 이름이 paxscript다음과 같다면...

cd -- "$1"
pax -rwvl \
    -s '|^.*/image1\.jpg$|&|' \
    -s '|^.*/photo3\.jpg$|&|' \
    -s '|^.*/redcar\.jpg$|&|' \
    -s '|^.*/balloon2323\.jpg$|&|' \
    -s '|.*||' ./ ../"${1##*/}.mirror"
cd - >/dev/null

...그리고 이렇게 실행하면...

. ./paxscript "$targetdir"

"$targetdir"일치시키려는 파일 이름에 대한 하드 링크만 포함하는 상위 디렉토리에 미러를 생성합니다. 그런 다음 실행하기 전에 결과가 원하는 대로 나타나는지 확인 rm -rf "$targetdir"하고 필요하지 않은 경로 이름을 제거할 수 있습니다.


답변4

만족하신다면 bash다음 알고리즘을 제공하고 싶습니다(모든 스크립팅 언어에서 구현 가능).

  1. 현재 파일 목록을 작성하십시오.find /path_to_folder -name "*.jpg" -fprint files.tmp
  2. 기준으로 정렬 files.tmp및 비교name.logcomm -23 files.tmp name.log
  3. files.tmprmto 명령과 관련된 파일 목록을 전달합니다.

파일 경로를 기록해 두십시오. 파일 경로는 둘 다에서 동일 files.tmp할 수 있습니다 name.log(전체 또는 폴더 기준). 이 경우 파일 이름 구분 기호 name.lognewline.

관련 정보