Удаление файлов на основе типов MIME в Linux

Я проверил это, и оно у меня сработало. Возможно, вы захотите выбрать другой временный шаблон вместо foobar. Без него sedудалил все между тегами, оставив толькоtext part 1 text part 3

sed -e 's/\/quote\]/foobar\]/3' -e 's/\[.*\/quote\]//' -e 's/\[.*foobar]//' testfile

вместо этого, если testfileвы можете просто передать это с помощьюcat

10
15.07.2020, 02:06
4 ответа

Соедините несколько инструментов в одну линию:

  • Используйте findи filesдля перечисления MIME-типа каждого файла (, как показано в вашем вопросе ).
  • Используйте awkдля фильтрации списка по типу.
  • Используйте xargs, чтобы взять этот отфильтрованный список и rmкаждый файл.

Я рекомендую вам использовать echo, чтобы rmне делал ничего первым. Это высушит -запуск команды, чтобы вы могли проверить, какие файлы она удалит!

Например, :для удаления "C source".

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

Затем запустите ту же строку, удаляющую echo, чтобы действительно удалить файлы.


Чтобы объяснить использование awk для фильтрации, пункт $(NF) ~ "C source"указывает awk сопоставлять любую строку со вторым столбцом (всем после :), содержащего 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
6
18.03.2021, 23:20

Чтобы удалить все файлы, в которых вывод fileначинается с имени файла, а : следует за ASCII text, используйте findи соответствие регулярному выражению bash:

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, если результат выглядит так, как ожидалось.

4
18.03.2021, 23:20

Поскольку вопрос помечен , вариант ответа Фредди:

(
  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
)
  • Подоболочка((... ))используется, чтобы избежать изменения IFSв основной среде.
  • IFSустанавливается на |, чтобы массив ${types[*]}расширялся до элементов, разделенных вертикальной чертой (обратите внимание на индекс *).
  • globstarзаставляет глобус ./**соответствовать всем файлам, каталогам и подкаталогам (, т. е. расширение имени файла рекурсивно спускается по дереву с корнем в текущем рабочем каталоге ).
  • dotglobделает так, что ./**также соответствует скрытым файлам.
  • Регулярное выражение (${types[*]})в составной команде[[расширяется до группового выражения ( ), состоящего из типов, разделенных символом чередования |, привязанных(^)к началу строки для снизить вероятность ложных срабатываний. Обратите внимание, что это, скорее всего, не будет работать, если члены typesсодержат специальные символы в POSIX расширенных регулярных выражениях(ERE ).

Удалите echo, когда вас удовлетворит список подлежащих -удалению файлов.

3
18.03.2021, 23:20

Поскольку вы находитесь в Баше, я бы пошел по этому пути:

#!/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'

Идея состоит в том, чтобы заполнить массив терминами, которые нужно удалить, а затем выполнить команду grep fileдля каждого файла.

Параметр -b, который подавляет имя файла из вывода file, используется для команды file, чтобы сценарий не прерывался, если имя файла содержит символы новой строки.

Первоначально сценарий только повторяет то, что он должен делать. Убедившись, что проблем нет, удалите 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
3
18.03.2021, 23:20

Теги

Похожие вопросы