find 명령의 출력을 정렬하고 다시 읽어 파일을 삭제합니다.

find 명령의 출력을 정렬하고 다시 읽어 파일을 삭제합니다.

다음 bash스크립트는 모든 디렉터리를 검색하고 각 디렉터리에 있는 파일 수를 나열합니다.

다음은 제가 직접 설치한 R 설치의 샘플 출력 테스트입니다. 정확히 제가 필요했던 것입니다.

find . -mindepth 6  -type d -print0 | while IFS= read -r -d '' i ; do echo -n $i": " ; ls -p "$i" | grep -v / | wc -l ; done

제 질문은 이 출력 "files.txt"(예를 들어)를 다음과 같은 다른 명령문으로 어떻게 읽을 수 있느냐는 것입니다.

xargs rm -f files.txt    # ("<" is missing)

모든 디렉터리가 포함된 files.txt의 내용을 읽고 여러 파일이 포함된 디렉터리의 모든 파일을 삭제하시겠습니까(폴더가 아닌 파일만, 디렉터리 구조를 변경하면 안 됨)?

아래 출력에서는 다음을 제외한 각 디렉터리의 모든 파일이 삭제됩니다.

./R/R-3.6.1/src/library/tcltk/R/windows: 1  
./R/R-3.6.1/src/library/compiler/man: 1   
./R/R-3.6.1/src/library/compiler/R: 1

예제 출력:

./R/R-3.6.1/src/library/tools/man: 64   
./R/R-3.6.1/src/library/tools/tests: 3   
./R/R-3.6.1/src/library/tools/src: 16  
./R/R-3.6.1/src/library/tools/po: 23  
./R/R-3.6.1/src/library/tools/R: 49    
./R/R-3.6.1/src/library/tcltk: 4   
./R/R-3.6.1/src/library/tcltk/man: 14  
./R/R-3.6.1/src/library/tcltk/exec: 12  
./R/R-3.6.1/src/library/tcltk/src: 7   
./R/R-3.6.1/src/library/tcltk/po: 21  
./R/R-3.6.1/src/library/tcltk/R: 6   
./R/R-3.6.1/src/library/tcltk/R/unix: 2  
./R/R-3.6.1/src/library/tcltk/R/windows: 1  
./R/R-3.6.1/src/library/tcltk/demo: 5  
./R/R-3.6.1/src/library/compiler: 4  
./R/R-3.6.1/src/library/compiler/man: 1  
./R/R-3.6.1/src/library/compiler/noweb: 2  
./R/R-3.6.1/src/library/compiler/tests: 10  
./R/R-3.6.1/src/library/compiler/po: 10  
./R/R-3.6.1/src/library/compiler/R: 1   
./R/R-3.6.1/src/library/graphics: 4

감사해요.

답변1

파일을 읽으려면 각 줄이 나열된 디렉터리의 모든 파일을 삭제 rm하라는 의미 있는 형식이어야 합니다 .rm

rm ./path/to/delete/*

그래서....

sed -E "s|:\s[0-9]+$|/*|" files.txt

파일의 각 시퀀스 공백, 하나 이상의 숫자 및 줄 sed:\s.[0-9]+$/*

그대로 입력하면 rm디렉토리 삭제도 요청하기 때문에 오류가 발생하므로 메시지에 오류가 표시되면 stderr를 리디렉션하십시오.

rm $(sed -E "s|:\s[0-9]+$|/*|" files.txt) 2>/dev/null

디렉토리 이름에 공백이 있으면 실패합니다. 이 경우 여전히 파일을 에 제공해야 합니다 . 나중에 변경하여 재설정 rm할 수 있습니다 .IFS

OFS=$IFS; IFS=$'\n'; rm $(sed -E "s|:\s[0-9]+$|/*|" files.txt) 2>/dev/null; IFS=$OFS

답변2

이 같은?

find . -type f -mindepth 6 \
  | sed -r 's:/[^/]+$::' \
  | sort \
  | uniq -c \
  | awk '$1 > 1 {print $2}' \
  | xargs -i% find % -type f -delete

무너지다

find . -type f -mindepth 6파일 목록 가져오기

sed -r 's:/[^/]+$::'파일 이름을 제거하고 디렉토리만 유지

sort다음 명령이 올바르게 작동해야 합니다.

uniq -c연속된 고유 행 수 계산

awk '$1 > 1 {print $2}'1개의 항목만 발견된 곳을 필터링하고 2개 이상의 파일을 남깁니다.

xargs -i% find % -type f -delete각 결과 디렉터리에서 파일을 검색하여 모두 삭제

일부 백플립 및 임시 파일을 사용하면 실행을 방지 xargs find하고 대신 입력에서 제거할 항목 목록을 얻을 수 있습니다.

답변3

어떤 디렉터리에 여러 파일이 포함되어 있는지 감지할 수 있는 방법이 이미 있고 결과가 파일(이라고 함 files.txt)에 저장되므로 셸 스크립트를 사용하여 작업을 수행할 수 있습니다.

#!/bin/bash

IFS=":"
while read path count
do
    if (( count > 1 ))
    then
        echo "Remove all files in $path (count = $count)"
        rm "$path/"*
    fi
done < files.txt

관련 정보