파일을 제거하지만 목록의 모든 파일을 제외


17

정기적으로 폴더를 정리해야합니다. 텍스트가 포함 된 파일 목록과 허용되는 파일을 얻습니다. 이제이 파일에없는 모든 파일을 삭제해야합니다.

예:

dont-delete.txt:

dontdeletethisfile.txt
reallyimportantfile.txt
neverdeletethis.txt
important.txt

내 폴더 정리에는 다음이 포함되어 있습니다.

ls /home/me/myfolder2tocleanup/:

dontdeletethisfile.txt
reallyimportantfile.txt
neverdeletethis.txt
important.txt
this-can-be-deleted.txt
also-waste.txt
never-used-it.txt

따라서이 파일을 삭제해야합니다.

this-can-be-deleted.txt
also-waste.txt
never-used-it.txt

파일에서 제공하는 일부 파일을 제외하는 옵션으로 삭제 명령을 작성하기 위해 무언가를 검색합니다.


이것은 숙제입니까?
mook765

당신이 그의 선생님이 아니길 바랍니다. lol
구자라트 산타나

2
@gujarat 우리는 무료 숙제 서비스가 아니므로 의견이 정당합니다. 질문 자체는 다른 사람들에게 유용 할 수 있으므로 지금까지 열려 있습니다.
Sergiy Kolodyazhnyy

@Serg 전적으로 당신에게 동의합니다
Gujarat Santana

답변:


9

rm명령을 확인하고는 필요에 작동하고 있음을 확인할 수 있도록 주석. 그런 다음 해당 줄의 주석을 해제하십시오.

check directory섹션에서는 실수로 잘못된 디렉토리에서 스크립트를 실행하고 잘못된 파일을 클로버하지 않도록합니다.

echo deleting줄을 제거하여 자동으로 실행할 수 있습니다 .

#!/bin/bash

cd /home/me/myfolder2tocleanup/

# Exit if the directory isn't found.
if (($?>0)); then
    echo "Can't find work dir... exiting"
    exit
fi

for i in *; do
    if ! grep -qxFe "$i" filelist.txt; then
        echo "Deleting: $i"
        # the next line is commented out.  Test it.  Then uncomment to removed the files
        # rm "$i"
    fi
done

쓸모없는 사용ls 과 출력의 쓸모없는 캡처 를 피하기 위해 코드가 편집 grep되어 일치하는 것이 있는지 여부가 있습니다. 또한 이스케이프 문제를 피하기 위해 고정 문자열 패턴을 사용했습니다.
David Foerster

@DavidFoerster 기부 해 주셔서 감사합니다. 그러나 while루프를 for루프로 변경하면 실수로 iteration key에서 i를 (으) 로 변경 했습니다 f. 선언에서 코드를 위반했습니다. 나는 그것을 고쳤다.
LD James

죄송합니다. 습관의 힘. 파일 이름에 대한 쉘 변수 이름을로 사용하는 경향이 f있습니다. ;-P (… 그리고 내가 이전에 잊어 버린 대답에 +1)
David Foerster

10

이 파이썬 스크립트는 이것을 할 수 있습니다 :

#!/usr/bin/env python3
import os
no_remove = set()
with open('./dont-delete.txt') as f:
     for line in f:
         no_remove.add(line.strip())

for f in os.listdir('.'):
    if f not in no_remove:
        print('unlink:' + f ) 
        #os.unlink(f)

중요한 부분은 os.unlink()기능 을 주석 해제하는 것입니다.

참고 :이 스크립트와 스크립트를 추가 dont-delete.txt하여 dont-delete.txt둘 다 목록에 있고 동일한 디렉토리에 보관하십시오.


1
set두 번째 부분에서 O (n) 조회 대신 O (1) 대신 목록 을 사용하도록 코드를 변경했습니다 .
David Foerster

귀하의 도움에 감사드립니다, 나는 일반적으로 Windows 사람이지만, 파이썬 이음새도 시원합니다 =)
stefan83

1
@ stefan83 : 파이썬은 Windows에서도 잘 실행됩니다.
David Foerster

3

하나의 라이너가 있습니다.

comm -2 -3 <(ls) <(sort dont_delete) | tail +2 | xargs -p rm
  1. ls 현재 디렉토리의 모든 파일을 정렬 된 순서대로 인쇄합니다
  2. sort dont_delete 삭제하지 않으려는 모든 파일을 정렬 된 순서로 인쇄합니다
  3. <()연산자는 파일 - 류의 객체로 문자열을 변
  4. comm명령은 두 개의 미리 정렬 된 파일을 비교하여 서로 다른 행을 인쇄합니다.
  5. -2 -3플래그를 사용하면 comm첫 번째 파일에 포함 된 행만 인쇄하고 두 번째 파일에는 인쇄하지 않고 삭제하는 것이 안전한 파일 목록이됩니다.
  6. tail +2호출은 단지의 제목 제거하는 것입니다 comm입력 파일의 이름이 포함 된 출력을,
  7. 이제 표준 출력에서 ​​삭제할 파일 목록을 얻습니다. 이 출력을 파이프 xargs하여 출력 스트림을의 인수 목록으로 바꿉니다 rm. 이 -p옵션은 xargs실행 전에 확인을 요구합니다.

당신의 도움을 위해 thx, 지금 나는 나의 해결책이있다!
stefan83

@gardenhead, 코드가 피곤했지만 디렉토리의 모든 파일을 제거하고 dont-delete 목록의 첫 번째 파일과 마지막 파일 만 유지합니다. 이 문제에 대한 아이디어가 있습니까? 미리 감사드립니다.
Negar

1

그래도 glob 한정자를 zsh사용하여에서 기본적 으로이 작업을 수행 할 수있는 것처럼 보입니다 (+cmd).

설명하기 위해 일부 파일부터 시작하겠습니다

 % ls
bar  baz  bazfoo  keepfiles.txt  foo  kazoo

화이트리스트 파일

 % cat keepfiles.txt
foo
kazoo
bar

먼저 화이트리스트를 배열로 읽습니다.

 % keepfiles=( "${(f)$(< keepfiles.txt)}" )

또는 아마도 더 나은

 % zmodload zsh/mapfile
 % keepfiles=( ${(f)mapfile[./keepfiles.txt]} )

(bash의 mapfile내장 또는 동의어와 동일 readarray). 이제 ${keepfiles[(I)filename]}일치하는 것이 없으면 0을 반환 하는 키를 사용하여 배열에 키 (파일 이름)가 있는지 확인할 수 있습니다 .

 % print ${keepfiles[(I)foo]}
1
 % print ${keepfiles[(I)baz]}
0
 %

이것을 사용 하여 배열에 true일치하는 것이 없으면 반환하는 함수를 만들 수 있습니다 $REPLY.

% nokeep() { (( ${keepfiles[(I)$REPLY]} == 0 )); }

마지막으로이 함수를 명령에서 한정자로 사용합니다.

 % ls *(+nokeep)
baz  bazfoo  keepfiles.txt

또는 귀하의 경우

 % rm -- *(+nokeep)

화이트리스트 파일 자체의 이름을 화이트리스트에 추가하고 싶을 것입니다.


0

bash 쉘이 extglob shopt설정되어 있다고 가정하면 다소 보수적 인 대안이 있습니다.

rm !($(tr \\n \| < keep.txt))

(... @gardenhead의 다른 우수한 통신 제안과 함께!)


0

Ubuntu 의 출력 ls /home/me/myfolder2tocleanup/최대 쉘 인수 제한 ARG_MAX 을 약 2MB 를 초과 하지 않는 한 다음을 제안합니다.


작업을 수행하는 한 줄 명령 구현은 다음과 같습니다.

  1. 다음 dont-delete.txt과 같이 삭제할 파일이 포함 된 디렉토리에 파일을 복사하십시오 .
cp dont-delete.txt /home/me/myfolder2tocleanup/
  1. cd 다음과 같이 삭제 될 파일이 들어있는 디렉토리로
cd /home/me/myfolder2tocleanup/
  1. 드라 이런을 수행하여 명령을 테스트하고 실제로 삭제하지 않고 삭제 된 것으로 탐지 된 파일의 이름을 인쇄하십시오.
ls -p | grep -v / | sed 's/\<dont-delete.txt\>//g' | sort | comm -3 - <(sort dont-delete.txt) | xargs echo | tr " " "\n"
  1. 출력에 만족하면 다음과 같이 명령을 실행하여 파일을 삭제하십시오.
ls -p | grep -v / | sed 's/\<dont-delete.txt\>//g' | sort | comm -3 - <(sort dont-delete.txt) | xargs rm

설명 :

  • ls -p현재 디렉토리의 모든 파일과 디렉토리 를 나열 하고 옵션 -p/디렉토리 이름에 a 를 추가 합니다.
  • grep -v //이름에 a 를 포함하는 모든 항목을 제거하여 디렉토리를 제외 합니다.
  • sed 's/\<dont-delete.txt\>//g'dont-delete.txt파일 을 제외 하므로 프로세스에서 삭제되지 않습니다.
  • sort의 나머지 출력을 정렬합니다 ls.
  • comm -3 - <(sort dont-delete.txt)dont-delete.txt파일 을 정렬하고 정렬 된 출력과 비교 ls하여 둘 다에 존재하는 파일 이름을 제외시킵니다.
  • xargs rm이미 처리 된의 출력에서 ​​나머지 파일 이름을 모두 제거합니다 ls. 현재의 모든 디렉토리에있는 항목을 제외하고 제거됩니다이 수단 디렉토리 , 에 나열된 파일 dont-delete.txt파일파일 자체dont-delete.txt

드라 이런 부분에서 :

  • xargs echo 제거해야 할 파일을 인쇄합니다.
  • tr " " "\n" 가독성을 높이기 위해 공백을 새 줄로 변환합니다.

0

rsync여기에 게시 된 솔루션 을 사용하는 것이 좋습니다 . 그렇지 않으면 언급 된 예외적 인 조건으로 아래 솔루션을 사용하십시오.

파일에 공백 파일 (공백 / 탭)이 없다고 가정하면 excludelist다음과 같이 할 수 있습니다.

find /path/to -type f \( ! -name "excludelist" $(printf ' -a ! -name %s\n' $(< excludelist)) \)

excludelist 파일에 -delete존재하지 않는 파일을 삭제하려면 위 명령에 추가 하십시오. 찾기에 옵션 이 없으면 다음 과 같이 사용할 수 있습니다 .-deleterm-exec

find /path/to -type f \( ! -name "excludelist" $(printf ' -a ! -name %s\n' $(< excludelist)) \) -exec echo rm {} \;

또는 사용 -exec+터미네이터 대신.

find /path/to -type f \( ! -name "excludelist" $(printf ' -a ! -name %s\n' $(< excludelist)) \) -exec echo rm {} +

echo 드라 이런에 사용됩니다.


-1

내 제안은 :

sed -e 's/^/\.\//' dont-delete.txt > dont-delete-relative-path.txt
find . -type f -print | grep -Fxvf dont-delete-relative-path.txt | xargs -d'\n' rm

2018-08-07 업데이트

예:

1: mkdir /tmp/delete-example && cd /tmp/delete-example
2: touch a b c d
3: echo "./a\n./b\n./dont-delete.txt\n" > dont-delete.txt
4: find . -type f -print | grep -Fxvf dont-delete.txt | xargs -d'\n' rm

3 행 뒤에는 dont-delete.txt내용 이 포함 된 파일이 있습니다.

./a
./b
./dont-delete.txt

(리딩 ./매우 중요합니다 )

파일 c및이 d삭제됩니다.


줄 바꿈으로 구분 된 파일 이름의 텍스트 파일로 이것을 시도했습니다. 디렉토리의 모든 파일이 삭제되었습니다.
자크 말라 프레이드

당신의 "유지 목록"이 틀렸다고 생각합니다.
NYXZ

예제 사용법을 추가했습니다.
nyxz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.