연도와 월별로 하위 폴더로 정렬된 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 -l
rm
편집하다: 제공된 명령은 name.log를 정규식 집합으로 처리합니다. @terdon name.log는 파일 이름 목록임을 기억하세요.
파일 이름이 일반적인 "일반" 문자를 사용하는 경우에는 충분할 수 있지만 다음과 같은 경우에는 문제가 발생할 수 있습니다.
- 파일 이름/정규식에는 등의 특이한 문자가 포함되어 있습니다
[
.]
(이 경우 일부 파일 삭제가 실패할 수 있으며 이름이 지정된 일부 파일이 삭제될 수도 있습니다name.log
!) 이를 방지하려면grep -F
에 특수 문자를 사용하거나 보호 할 수 있습니다name.log
. - 정규식은 파일 이름의 하위 문자열과 일치합니다(이 경우 일부 파일은 삭제되지 않습니다.
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
여기서 두 번째 파일은 파이프의 내용을 자세히 설명합니다 . 위의 내용은 다음과 같습니다.tar
pax
pax
-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
다음 알고리즘을 제공하고 싶습니다(모든 스크립팅 언어에서 구현 가능).
- 현재 파일 목록을 작성하십시오.
find /path_to_folder -name "*.jpg" -fprint files.tmp
- 기준으로 정렬
files.tmp
및 비교name.log
comm -23 files.tmp name.log
files.tmp
rm
to 명령과 관련된 파일 목록을 전달합니다.
파일 경로를 기록해 두십시오. 파일 경로는 둘 다에서 동일 files.tmp
할 수 있습니다 name.log
(전체 또는 폴더 기준). 이 경우 파일 이름 구분 기호 name.log
는 newline
.