У меня есть каталог, который содержит следующее:
x.pdf
y.zip
z.mp3
a.pdf
Я хочу удалить все файлы кроме x.pdf
и a.pdf
. Как я делаю это от терминала? Нет никаких подкаталогов так никакая потребность ни в какой рекурсии.
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
средства удалить его.
!
должен прибыть прежде -name
. просто -name
будет включать только .pdf
, в то время как -iname
будет включать обоих .pdf
и .PDF
Для удаления только в текущем каталоге а не в подкаталогах добавляют -maxdepth 1
:
find . -maxdepth 1 -type f ! -iname "*.pdf" -delete
$ cd <the directory you want>
$ gvfs-trash !(*.pdf)
Или через mv
команда (но таким образом Вы не можете восстановить его от Мусора, так как это не записывает .trashinfo информацию, таким образом, это означает, Вы переместили свои файлы в место назначения , где это как следует).
mv !(*.pdf) ~/.local/share/Trash/files
Самый легкий подход: Создайте другой каталог где-нибудь (если Вы только удаляете в одном каталоге, не рекурсивно, это может даже быть подкаталог); переместите весь .pdf туда; удалите все остальное; положите обратно PDF; удалите промежуточный каталог.
Быстрый, легкий, Вы видите точно, что Вы делаете. Просто удостоверьтесь, что промежуточный каталог находится на том же устройстве как каталог, который Вы очищаете так, чтобы перемещения были, переименовывает, не копии!
Используйте 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
Я обычно решаю такие проблемы от интерактивного интерпретатора Python:
mic@mic ~ $ python
>>> import os
>>> for f in os.listdir('.'):
... if not f.endswith('.pdf'):
... os.remove(f)
Это могло бы быть более длинно, чем острота с find
или xargs
, но это чрезвычайно эластично, и я знаю точно, что это делает, не имея необходимость исследовать его сначала.
rm $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
Предупреждение! Лучше попробуйте сначала
ls -l $(ls -lo|grep -v [Pp][Dd][Ff]$|awk '{print $7}')
лучший ответ (по сравнению с моим предыдущим ответом) к этому вопросу будет при помощи мощного 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.
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
Остерегаться того, что Вы удаляете!
А безопасный способ протестировать это прежде, чем попытаться удалить должно протестировать сначала с 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*)
С 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
Вот подход, который я люблю, потому что он позволяет мне быть очень осторожным: составьте способ показать просто файлы, которые я хочу удалить, затем отправить их в 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
, и т.д.
$ 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 -c 'import os;map(lambda x: os.remove(x), filter(lambda x: not x.endswith(".pdf"),os.listdir(".")))'
Это решение подходит для большинства случаев.
У меня есть сотни каталогов, но есть исключения для некоторых файлов каталогов.
Заархивируйте все файлы, которые не подлежат удалению, в my_files.zip
. Если есть каталоги, вам нужно добавить рекурсивную команду.
zip -r my_files.zip a.php b.txt c.dll каталог1 каталог2
Удалите все файлы рекурсивно (тщательно), кроме myfiles.zip
#extended globbing позволяет более сложное сопоставление шаблонов.
shopt -s extglob
#удалить весь файл
rm -r -- !(my_files.zip)
Распаковать my_files.zip
распаковать my_files.zip