Я проверил это, и оно у меня сработало. Возможно, вы захотите выбрать другой временный шаблон вместо foobar
. Без него sed
удалил все между тегами, оставив толькоtext part 1 text part 3
sed -e 's/\/quote\]/foobar\]/3' -e 's/\[.*\/quote\]//' -e 's/\[.*foobar]//' testfile
вместо этого, если testfile
вы можете просто передать это с помощьюcat
Соедините несколько инструментов в одну линию:
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
Чтобы удалить все файлы, в которых вывод 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
, если результат выглядит так, как ожидалось.
Поскольку вопрос помечен bash , вариант ответа Фредди:
(
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
, когда вас удовлетворит список подлежащих -удалению файлов.
Поскольку вы находитесь в Баше, я бы пошел по этому пути:
#!/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