Linux에서 MIME 유형을 기반으로 파일 삭제

Linux에서 MIME 유형을 기반으로 파일 삭제

저는 Linux를 처음 사용하는데 MIME 유형을 기반으로 파일을 삭제하는 데 문제가 있습니다. 현재 내 Linux 시스템에는 파일 세트가 있으며 아래에는 일부 유형이 선택되어 있습니다.

0FiTahKc: M3U playlist, ASCII text, with very long lines, with CRLF line terminators
0FJsEpTc: ASCII text, with CRLF line terminators
0fKPkmwe: ASCII text, with CRLF line terminators
0FLR6MWB: ASCII text
0FMa2xL2: C source, ASCII text, with CRLF line terminators
0fN8DDbf: exported SGML document, ASCII text, with very long lines, with no line terminators
0fSM3YyG: ASCII text, with CRLF line terminators
0fTXKtZD: UTF-8 Unicode text, with CRLF line terminators
0FUcusxr: ASCII text, with CRLF line terminators

디렉토리에 있는 다양한 유형의 파일을 살펴보았는데 결과는 다음과 같습니다.

$ find -type f -exec file {} \; | sed 's/^.*: //' | sort -u

ASCII text
ASCII text, with CRLF line terminators
ASCII text, with no line terminators
ASCII text, with very long lines, with CRLF line terminators
ASCII text, with very long lines, with no line terminators
C source, ASCII text, with CRLF line terminators
exported SGML document, ASCII text, with very long lines, with no line terminators
M3U playlist, ASCII text, with very long lines, with CRLF line terminators
M3U playlist, UTF-8 Unicode text, with CRLF line terminators
UTF-8 Unicode text, with CRLF line terminators

"C Source", "M3U Playlist", "SGML" 등에 대해 grep을 사용하거나 Find를 사용하여 디렉토리에서 해당 파일을 삭제하고 싶습니다(처음 5줄의 ASCII 유형 제외). 이러한 파일 형식의 다양한 유형을 파이프하고 삭제할 수 있는 실행할 수 있는 명령이나 스크립트를 찾고 있습니다.

답변1

몇 가지 도구를 한 줄에 함께 넣으십시오.

  • 질문에 표시된 대로 각 파일의 MIME 유형을 사용 find하고 나열하십시오.files
  • awk유형을 기준으로 목록을 필터링 하는 데 사용됩니다 .
  • xargs필터링된 목록과 각 파일을 가져오는 데 사용됩니다 rm.

echo아무것도 하지 않도록 먼저 사용하는 것이 좋습니다 . rm그러면 명령이 건조 실행되어 어떤 파일이 삭제될지 확인할 수 있습니다!

예: "C 소스"를 삭제합니다.

find . -type f -exec file {} + | awk -F: '$(NF) ~ "C source" {print $1}' | xargs echo rm

그런 다음 동일한 줄 삭제를 실행하여 echo실제로 파일을 삭제합니다.


awk를 사용한 필터링을 설명하기 위해 이 절은 awk에게 $(NF) ~ "C source"두 번째 열( a 이후의 모든 항목 ) :에 포함된 모든 행 과 일치하도록 지시합니다 C source. 이 조건은 원하는 대로 확장될 수 있습니다. 따라서 가장 확실하게 다음을 검색 C Source하거나 M3U playlist사용할 수 있습니다.

$(NF) ~ "C source" || $(NF) ~ "M3U playlist"

예:

find . -type f -exec file {} + | awk -F: '$(NF) ~ "C source" || $2 ~ "M3U playlist" {print $1}' | xargs echo rm

답변2

file출력이 파일 이름 :과 bash 정규식 일치로 시작하는 모든 파일을 제거하려면 다음을 수행하십시오 ASCII text.find

find -type f -exec bash -c '
  for f; do
    file=$(file -- "$f")
    if [[ $file =~ ^$f:\ "ASCII text" ]]; then
      echo rm -- "$f"
    fi
  done
' bash {} +

C source, M3U playlist또는 에도 동일 exported SGML document:

find -type f -exec bash -c '
  for f; do
    file=$(file -- "$f")
    if [[ $file =~ ^$f:\ ("C source"|"M3U playlist"|"exported SGML document") ]]; then
      echo rm -- "$f"
    fi
  done
' bash {} +

출력이 예상대로 나타나면 echo이전 콘텐츠를 삭제하세요.rm

답변3

당신이 Bash에 있기 때문에 나는 다음 경로로 갈 것입니다:

#!/bin/bash
[ "$#" -ge 1 ] || { >&2 echo Supply at least one substring; exit 9; }
find . -type f -exec bash -c '
    terms=()
    nargs=$1
    shift
    for ((i=1;i<=nargs;i++)); do
        terms+=("-e")
        terms+=("$1")
        shift
    done
    for f; do
        if file -b -- "$f" | grep -Fq "${terms[@]}"; then
            echo rm -- "$f"
        fi
    done
' find-bash "$#" "$@" {} +

다른 이름으로 저장하고 다음을 사용 script.bash하여 chmod a+x script.bash실행 가능하게 만듭니다.

./script.bash 'C source' 'M3U playlist' 'SGML'

아이디어는 제거할 용어로 배열을 채운 다음 file각 파일에 대한 명령 출력을 grep하는 것입니다.

이 옵션은 명령 -b출력에서 ​​파일 이름을 억제하므로 파일 이름에 개행 문자가 포함되어 있어도 스크립트가 중단되지 않습니다.filefile

처음에 스크립트는 수행할 작업을 에코합니다. 문제가 없다고 확신되면 라인 echo에서 제거하십시오. rm몇 가지 실행 예( A<newline>B문서 참고):

$ file *
a b:                 empty
A
B:                 awk or perl script, ASCII text
Active.png:          PNG image data, 640 x 384, 8-bit/color RGB, non-interlaced
blanks.bash:         Bourne-Again shell script, ASCII text executable
covidActive.gnuplot: ASCII text
data.dat:            ASCII text
script.bash:         Bourne-Again shell script, ASCII text executable
table.txt:           ASCII text
test.sh:             POSIX shell script, ASCII text executable
$ ./script.bash awk shell
rm -- ./script.bash
rm -- ./blanks.bash
rm -- ./test.sh
rm -- ./A
B
$ ls
'a b'   Active.png   covidActive.gnuplot   data.dat   table.txt

답변4

질문에 태그가 지정되었으므로, 변형프레디의 대답:

(
  types=( "C source" "M3U playlist" "exported SGML document" )
  IFS='|'
  shopt -s globstar dotglob
  for f in ./**; do
    if [[ $(file -b -- "$f") =~ ^(${types[*]}) ]]; then
      echo rm -- "$f"
    fi
  done
)
  • Subshell( )은 기본 환경의 변경을 ( ... )방지하기 위해 사용됩니다 .IFS
  • IFS배열이 파이프로 구분된 해당 멤버로 확장되도록 설정합니다( |아래 첨자 참고).${types[*]}*
  • globstarglob이 모든 파일, 디렉터리 및 하위 디렉터리와 일치하도록 합니다 ./**(즉, 파일 이름 확장자는 현재 작업 디렉터리에 루트가 있는 트리를 반복적으로 내려갑니다).
  • dotglob./**숨겨진 파일 도 일치시킬 수 있습니다 .
  • (${types[*]})정규식[[ 복합 명령대체 기호 ( )로 분리된 유형으로 구성된 그룹 표현식 으로 확장되고, 문자열 시작 부분에 |고정( )되어 잘못된 긍정의 가능성을 줄입니다. 멤버가 POSIX에 특수 문자를 포함하는 경우 작동하지 않을 수 있습니다 ^.types확장 정규식(오히려).

echo삭제할 파일 목록이 만족스러우면 삭제하세요.

관련 정보