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

いくつかのツールを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"2番目の列(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 textfind

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 sourceM3U 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
)
  • Subshel​​l()は、基本環境の変更を( ... )防ぐために使用されます。IFS
  • IFS配列をパイプで区切られた対応するメンバーに拡張するように設定します(|下付き文字を参照)。${types[*]}*
  • globstarglobがすべてのファイル、ディレクトリ、およびサブディレクトリと一致するようにします./**(つまり、ファイル名拡張子は現在の作業ディレクトリにルートを持つツリーを繰り返しダウンさせます)。
  • dotglob./**隠しファイルも一致させることができます。
  • (${types[*]})正規表現[[ 複合コマンド置換記号( )で区切られた型からなるグループ式に展開され、文字列の先頭に|固定()され、誤った肯定の可能性を減らします。メンバーがPOSIXに特殊文字を含む場合は機能しない可能性があります^types拡張正規表現(むしろ)。

echo削除するファイルのリストが満足であれば、削除してください。

関連情報