在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 源”、“M3U 播放列表”和“SGML”等的 grep 或使用“查找”并从目录中删除这些文件(前 5 行中的 ASCII 类型除外)。我正在寻找可以运行的命令或脚本,可以在其中通过管道传送这些文件类型的不同类型并删除它们。

答案1

将一些工具拼凑成一行:

  • 使用findfiles列出每个文件的 mime 类型(如您的问题所示)。
  • 用于awk根据类型过滤该列表。
  • 用于xargs获取过滤列表和rm每个文件。

我建议您首先使用echo来阻止做任何事情。rm这将空运行该命令,以便您可以检查它将删除哪些文件!

例如:删除“C 源”。

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

然后运行同一行删除echo来实际删除文件。


为了解释使用 awk 进行过滤,该子句$(NF) ~ "C source"告诉 awk 匹配第二列(a 之后的所有内容:)包含 的任何行C source。这个条件可以扩展到你喜欢的任何东西。因此,最明显的是,您可以搜索C SourceM3U 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 playlistexported 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'

这个想法是用要删除的术语填充一个数组,然后 grepfile每个文件的命令输出。

-b选项可从 的输出中抑制文件名file,用于file命令,以便在文件名包含换行符时脚本不会中断。

最初,脚本只是回显它会做什么。一旦确信没有问题,请将其echorm线路中删除。一些示例执行(注意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
)
  • 子 shell ( ( ... )) 用于避免IFS主环境发生变化。
  • IFS设置为|以使${types[*]}数组扩展到其由竖线分隔的成员(注意*下标)。
  • globstar使./**glob 匹配所有文件、目录和子目录(即文件名扩展以当前工作目录为根的树递归下降)。
  • dotglob还可以./**匹配隐藏文件。
  • (${types[*]})中的正则表达式[[ 复合命令扩展为由交替符号( )分隔的类型组成的组表达式|,锚定 ( ^) 到字符串的开头以降低误报的可能性。请注意,如果 的成员types包含 POSIX 中的特殊字符,则这可能不起作用扩展正则表达式(ERE)。

echo当您对要删除的文件列表感到满意时,删除。

相关内容