폴더에 /photo
많은 파일이 있다고 가정합니다.
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
10.jpg
nodeletelist.txt
이 텍스트 파일에는 삭제하지 않을 파일 목록의 이름과 함께 파일 이름이 있습니다.
1.jpg
2.jpg
3.jpg
nodeletelist.txt
파일을 삭제하는 방법:
4.jpg
...
10.jpg
파일을 제외하고 1.jpg
, 2.jpg
및 무엇 3.jpg
입니까 ?nodeletelist.txt
nodeletelist.txt
답변1
GNU 발견이 있나요?
find photo -mindepth 1 -maxdepth 1 -regextype awk \! -regex ".*/($(tr '\n' '|' < photo/nodeletelist.txt)nodeletelist.txt)" -delete
이는 tr(1)
및 를 사용하여 달성됩니다 find(1)
.
- 파일을 다음으로 리디렉션
tr
- 줄 바꿈을 "OR"을 의미하는 수직 막대로 바꿉니다.
- 서브쉘에서 복귀
- 파일이 개행으로 끝나는 경우 끝에 플래그 값을 추가하십시오. (이 예에서는 귀하의 이름을 감시자로 사용하므로
nodeletelist.txt
이 솔루션을 사용하는 경우 파일에 파일 이름을 포함할 필요가 없습니다.) - 디렉토리에서 한 수준 아래 항목을 검색하세요.
photo
- awk 정규식을 사용하여 위의 1~4단계에서 반환된 문자열을 일치시킵니다.
- 파일 삭제아니요정규식과 일치함(
!
"NOT"을 의미하므로)
여기에 필요한 확장 구문이 해당 플래그에 적용되므로 여기 플래그는 , , 또는 -regextype
로 설정할 수도 있습니다 . 기본 findutils 정규식, posix-basic, emacs, sed 등은 이 명령에서 작동하지 않습니다.posix-extended
egrep
posix-egrep
gnu-awk
posix-awk
답변2
zsh
그것이 옵션 이라면 , 다음과 같이 사용할 쉘 함수를 정의할 수 있습니다.글로벌 예선"는 glob의 모든 파일 목록을 필터링하는 데 사용됩니다 *
. 예를 들어
% cmd() { ! grep -qF "$REPLY" ./nodeletelist.txt ; }
그런 다음 ( photo/
디렉토리에서)
% ls
10.jpg 1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg nodeletelist.txt
% ls *(+cmd)
10.jpg 4.jpg 5.jpg 6.jpg 7.jpg 8.jpg 9.jpg
괜찮아 보이는데 삭제하자
% rm *(+cmd)
% ls
1.jpg 2.jpg 3.jpg nodeletelist.txt
먼저 파일을 배열로 매핑한 다음 해당 파일이 $REPLY
배열의 요소인지 테스트하는 보다 효율적인 구현이 있을 수 있습니다.
답변3
나에게는 가장 간단하고 기억하기 쉬우며 많은 파일에서도 작동합니다(파일 이름의 줄 바꿈에서 생각이 깨질 수 있지만 그런 경우 목록에 대해 생각해야 합니다).
cd /photo
ls -1 | grep -v -x -f nodeletelist.txt | xargs -d "\n" -P 0 rm -f
디렉터리에 다른 항목(하위 디렉터리 또는 다른 파일, 목록에 txt가 포함되어 있다고 가정하지 않음)이 있는 경우 ls 대신 find I를 사용합니다( find . -maxdepth 1 -type f -name "*.jpg"
예:).
답변4
설명된 이름에 공백이 없는 경우
rm $(join -v 1 <(ls *.jpg) <(sed '$ d' nodeletelist.txt))
nodeletelist.txt 파일의 마지막 줄을 실제로 읽었다고 가정합니다.nodeletelist.txt
그렇지 않다면,
rm $(join -v 1 <(ls *.jpg) nodelete.txt)
근데 별로 고급스러운 느낌은 아닌데...