Удалите все файлы кроме файлов с дополнительным PDF в каталоге

У меня есть каталог, который содержит следующее:

x.pdf
y.zip
z.mp3
a.pdf

Я хочу удалить все файлы кроме x.pdf и a.pdf. Как я делаю это от терминала? Нет никаких подкаталогов так никакая потребность ни в какой рекурсии.

50
задан 18 May 2015 в 02:36

13 ответов

cd <the directory you want>
find . -type f ! -iname "*.pdf" -delete
  • Первая команда возьмет Вас к каталогу, в котором Вы хотите удалить свои файлы
  • Вторая команда удалит все файлы кроме с теми, которые заканчиваются .pdf в имени файла

Например, если существует названный каталог temp в Вашей домашней папке:

cd ~/temp

затем удалите файлы:

find . -type f ! -iname "*.pdf" -delete

Это удалит все файлы кроме xyz.pdf.

Можно объединить эти две команды к:

find ~/temp -type f ! -iname "*.pdf" -delete

. текущий каталог. ! средства взять все файлы кроме тех с .pdf в конце. -type f выбирает только файлы, не каталоги. -delete средства удалить его.

Примечание: эта команда удалит все файлы (кроме файлов PDF, но включая скрытые файлы) в текущем каталоге, а также во всех подкаталогах. ! должен прибыть прежде -name. просто -name будет включать только .pdf, в то время как -iname будет включать обоих .pdf и .PDF

Для удаления только в текущем каталоге а не в подкаталогах добавляют -maxdepth 1:

find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
63
ответ дан 22 November 2019 в 23:51

Удаляют к мусору :

$ cd <the directory you want>
$ gvfs-trash !(*.pdf)

Или через mv команда (но таким образом Вы не можете восстановить его от Мусора, так как это не записывает .trashinfo информацию, таким образом, это означает, Вы переместили свои файлы в место назначения , где это как следует).

mv !(*.pdf) ~/.local/share/Trash/files
18
ответ дан 22 November 2019 в 23:51

Самый легкий подход: Создайте другой каталог где-нибудь (если Вы только удаляете в одном каталоге, не рекурсивно, это может даже быть подкаталог); переместите весь .pdf туда; удалите все остальное; положите обратно PDF; удалите промежуточный каталог.

Быстрый, легкий, Вы видите точно, что Вы делаете. Просто удостоверьтесь, что промежуточный каталог находится на том же устройстве как каталог, который Вы очищаете так, чтобы перемещения были, переименовывает, не копии!

14
ответ дан 22 November 2019 в 23:51

Используйте GLOBIGNORE удара:

GLOBIGNORE=x.pdf:a.pdf
rm *
unset GLOBIGNORE

Из страницы справочника удара:

GLOBIGNORE:

            A colon-separated list of patterns defining the set
            of filenames to be ignored by pathname expansion.
<час>

А быстрый тест:

mkdir /tmp/foooooo
cd /tmp/foooooo
touch x.pdf y.zip z.mp3 a.pdf
GLOBIGNORE=x.pdf:a.pdf
ls -1 *

Вывод:

y.zip
z.mp3
4
ответ дан 22 November 2019 в 23:51

Я обычно решаю такие проблемы от интерактивного интерпретатора Python:

mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
...   if not f.endswith('.pdf'):
...     os.remove(f)

Это могло бы быть более длинно, чем острота с find или xargs, но это чрезвычайно эластично, и я знаю точно, что это делает, не имея необходимость исследовать его сначала.

3
ответ дан 22 November 2019 в 23:51
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')

Предупреждение! Лучше попробуйте сначала

ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
1
ответ дан 22 November 2019 в 23:51

лучший ответ (по сравнению с моим предыдущим ответом) к этому вопросу будет при помощи мощного file команда.

$ file -i abc.pdf
abc: application/pdf; charset=binary

теперь Ваша проблема:

cd <the directory you want to search in>
for var in ./*
do
if file -i "$var" | grep -q 'application/pdf\;'
then
echo "$var"
fi
done

задание for, который команда, дает файлы в текущем каталоге в форме переменной $var. if-then команда производит названия файлов PDF путем взятия статуса выхода 0 от file -i "$var" | grep -q 'application/pdf\;' команда, это даст статус выхода 0, только если это находит файлы PDF.

2
ответ дан 22 November 2019 в 23:51
rm -i -- !(*@(a|x).pdf)

Read как, удалите все файлы, которые не являются a.pdf или x.pdf.

Это работает путем использования 2 расширенных шариков, внешнее !() для отрицания содержавшего шарика, который самого требует, чтобы шарик соответствовал одному или нескольким из a или x шаблоны перед эти .pdf суффикс. См. glob#extglob.

$ ls -a
.dotfile1 .dotfile2 a.pdf x.pdf y.zip z.mp3

$ echo -- !(a.pdf)
-- x.pdf y.zip z.mp3

$ echo -- !(x.pdf)
-- a.pdf y.zip z.mp3

$ echo -- !(a.pdf|x.pdf)
-- y.zip z.mp3

$ echo -- !(@(a|x).pdf)   # NOTE.that this matches the .dotfiles* as well
-- . .. .dotfile1 .dotfile2 y.zip z.mp3

$ echo -- !(*@(a|x).pdf)  # but this doesn't
-- y.zip z.mp3

$ echo rm -i -- !(*@(a|x).pdf)
rm -i -- y.zip z.mp3
1
ответ дан 22 November 2019 в 23:51

Остерегаться того, что Вы удаляете!

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

ls sub/path/to/files/!(*.pdf)

Это перечислит

y.zip
z.mp3

, И теперь Вы видите то, что Вы удаляете и можете безопасно удалить их:

rm sub/path/to/files/!(*.pdf)

И вот именно. Эй может использовать подстановочный знак *, чтобы быть более выборочным как хранение, только программируя документы курса:

rm sub/path/to/files/!(*programming*)
0
ответ дан 22 November 2019 в 23:51

С bashрасширенная оболочка globbing, Вы могли удалить любые файлы с расширениями кроме .pdf использование

rm -- *.!(pdf)

Как отмечено @pts, -- символы указывают на конец любых опций команды, делают команду безопасной в редком случае файлов, имена которых запускаются с a - символ.

Если Вы хотите удалить файлы без какого-либо расширения, а также тех, которые имеют расширения кроме .pdf, затем, как указано @DennisWilliamson Вы могли использовать

rm -- !(*.pdf)

Расширенный globbing должен быть включен по умолчанию, но если не можно сделать настолько использующий

shopt -s extglob

Особенно, если Вы намереваетесь использовать эту внутреннюю часть сценарий, важно отметить что, если выражение ничему не будет соответствовать (т.е. если не будет никаких файлов не-PDF в каталоге), то по умолчанию шарик будет передан нерасширенный до rm команда, приводящая к ошибке как

rm: cannot remove `*.!(pdf)': No such file or directory

Можно изменить это поведение по умолчанию с помощью nullglob опция оболочки, однако который имеет ее собственную проблему. Поскольку более полное обсуждение видит NullGlob - Wiki Greg

43
ответ дан 22 November 2019 в 23:51

Будьте осторожны и сочините: используйте xargs

Вот подход, который я люблю, потому что он позволяет мне быть очень осторожным: составьте способ показать просто файлы, которые я хочу удалить, затем отправить их в rm использование xargs. Например:

  • ls показывает мне все
  • ls | grep pdf показывает мне файлы, которые я хочу сохранить. Хм.
  • ls | grep -v pdf шоу противоположное: все кроме того, что я хочу сохранить. Другими словами, это показывает список вещей, которые я хочу удалить. Я могу подтвердить это прежде, чем сделать что-либо опасное.
  • ls | grep -v pdf | xargs rm отправляет точно тот список в rm для удаления

Как я сказал, мне главным образом нравится это за безопасность, которую это обеспечивает: никакой случайный элемент rm * для меня. Два других преимущества:

  • Это компонуемо; можно использовать ls или find получить первоначальный список, как Вы предпочитаете. Можно использовать что-либо еще, что Вы любите в процессе сужения того списка - другой grep, некоторые awk,или что бы то ни было. Если бы необходимо было удалить только файлы, имена которых содержат цвет, Вы могли создать его этот тот же путь.
  • Можно использовать каждый инструмент для его основной цели. Я предпочитаю использовать find для нахождения и rm для удаления, в противоположность необходимости помнить это find принимает a -delete флаг. И если Вы делаете это, снова, можно составить альтернативные решения; возможно, вместо rm, Вы могли создать a trash управляйте, чтобы переместил файл в мусор (позволяющий "восстановление после удаления") и канал к этому вместо rm. Вы не должны иметь find поддерживайте ту опцию, Вы просто передаете по каналу к ней.

Обновление

См. комментарии @pabouk для того, как изменяют это для обработки некоторых пограничных случаев, таких как разрывы строки в именах файлов, именах файлов как my_pdfs.zip, и т.д.

3
ответ дан 22 November 2019 в 23:51

портативная оболочка путь

$ ksh -c 'for i in ./*; do case $i in *.pdf)continue;; *)rm "$i";; esac;done'

В значительной степени POSIX и совместимый с любой оболочкой стиля Границы ( ksh, bash, dash ). Хорошо удовлетворенный для портативных сценариев и когда Вы не можете использовать bashрасширенная оболочка globbing.

жемчуг:

$ perl -le 'opendir(my $d,"."); foreach my $f (grep(-f && !/.pdf/ , readdir($d))){unlink $f};closedir $d'                                                             

Или немного более чистый:

$ perl -le 'opendir(my $d,"."); map{ unlink $_ } grep(-f "./$_" && !/.pdf/ , readdir($d));closedir $d'

альтернативный Python

python -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
1
ответ дан 22 November 2019 в 23:51

Это решение подходит для большинства случаев.

У меня есть сотни каталогов, но есть исключения для некоторых файлов каталогов.

  1. Заархивируйте все файлы, которые не подлежат удалению, в my_files.zip. Если есть каталоги, вам нужно добавить рекурсивную команду.

    zip -r my_files.zip a.php b.txt c.dll каталог1 каталог2
    
  2. Удалите все файлы рекурсивно (тщательно), кроме myfiles.zip

    #extended globbing позволяет более сложное сопоставление шаблонов.
    shopt -s extglob
    
    #удалить весь файл
    rm -r -- !(my_files.zip)
    
  3. Распаковать my_files.zip

    распаковать my_files.zip
    
0
ответ дан 14 May 2020 в 03:31

Другие вопросы по тегам:

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