Мне периодически нужна к очистке папка. Я получаю список файлов, который содержит текст, который позволяются файлы. Теперь я должен удалить все файлы, которые не находятся в этом файле.
Пример:
dont-delete.txt
:
dontdeletethisfile.txt
reallyimportantfile.txt
neverdeletethis.txt
important.txt
Моя папка делает очистка содержит это как пример:
ls /home/me/myfolder2tocleanup/
:
dontdeletethisfile.txt
reallyimportantfile.txt
neverdeletethis.txt
important.txt
this-can-be-deleted.txt
also-waste.txt
never-used-it.txt
Таким образом, это регистрирует, должен быть удален:
this-can-be-deleted.txt
also-waste.txt
never-used-it.txt
Я ищу что-то для создания удалить команды с опцией исключить некоторые файлы, обеспеченные файлом.
Команда rm
закомментирована, так что вы можете проверить и убедиться, что она работает по мере необходимости. Тогда просто откомментируйте эту строку.
Раздел check directory
гарантирует, что вы случайно не запустите скрипт из неправильного каталога и не забьете неправильные файлы.
Вы можете удалить строку echo deleting
для бесшумной работы.
#!/bin/bash
cd /home/me/myfolder2tocleanup/
# Exit if the directory isn't found.
if (($?>0)); then
echo "Can't find work dir... exiting"
exit
fi
for i in *; do
if ! grep -qxFe "$i" filelist.txt; then
echo "Deleting: $i"
# the next line is commented out. Test it. Then uncomment to removed the files
# rm "$i"
fi
done
Этот сценарий Python может сделать это:
#!/usr/bin/env python3
import os
no_remove = set()
with open('./dont-delete.txt') as f:
for line in f:
no_remove.add(line.strip())
for f in os.listdir('.'):
if f not in no_remove:
print('unlink:' + f )
#os.unlink(f)
Важная часть должна не прокомментировать эти os.unlink()
функция.
ПРИМЕЧАНИЕ : добавьте этот сценарий и dont-delete.txt
к Вашему dont-delete.txt
так, чтобы они оба были в списке и сохранили их в том же каталоге.
Вот одна строка:
comm -2 -3 <(ls) <(sort dont_delete) | tail +2 | xargs -p rm
ls
печатает все файлы в текущем каталоге (в отсортированном порядке) sort dont_delete
печатает все файлы, которые мы не хотите удалять в отсортированном порядке <()
превращает строку в файлоподобный объект comm
сравнивают два предварительно отсортированных файла и выводят строки для которых они различаются -2 -3
заставляет comm
печатать только строки, содержащиеся в первом файле, но не во втором, что будет списком файлов, которые можно безопасно удалить tail +2
предназначен только для удаления заголовка вывода comm
, который содержит имя входного файла xargs
, который превратит выходной поток в список аргументов для rm
. Опция -p
заставляет xargs
запрашивать подтверждение перед выполнением. Предположение, что Ваша оболочка удара имеет extglob
shopt
набор к на, вот является несколько более консервативной альтернативой:
rm !($(tr \\n \| < keep.txt))
(... в других отношениях превосходное предложение коммуникации сопроводительного @gardenhead!)
FWIW это похоже на Вас, может сделать это исходно в zsh
, использование (+cmd)
спецификатор шарика.
Для иллюстрирования давайте запустимся с некоторых файлов
% ls
bar baz bazfoo keepfiles.txt foo kazoo
и файл белого списка
% cat keepfiles.txt
foo
kazoo
bar
Во-первых, прочитайте белый список в массив:
% keepfiles=( "${(f)$(< keepfiles.txt)}" )
или возможно лучше
% zmodload zsh/mapfile
% keepfiles=( ${(f)mapfile[./keepfiles.txt]} )
(эквивалент удара mapfile
встроенный - или его синоним readarray
). Теперь мы можем проверить, существует ли ключ (имя файла) в использовании массива ${keepfiles[(I)filename]}
который возвращается 0, если никакое соответствие не найдено:
% print ${keepfiles[(I)foo]}
1
% print ${keepfiles[(I)baz]}
0
%
Мы можем использовать это для создания функции, которая возвращается true
при отсутствии соответствий для $REPLY
в массиве:
% nokeep() { (( ${keepfiles[(I)$REPLY]} == 0 )); }
Наконец, мы используем эту функцию в качестве спецификатора в нашей команде:
% ls *(+nokeep)
baz bazfoo keepfiles.txt
или, в Вашем случае
% rm -- *(+nokeep)
(Вы, вероятно, захотите добавить название самого файла белого списка к белому списку.)
Принятие там не является никаким пробелом (Пробелы/Вкладки) в Ваших файлах, перечисленных в названном файле list
, затем Вы сделали бы:
find /path/to -type f \( ! -name "list" $(printf ' -a ! -name %s\n' $(< list)) \)
Просто добавьте -delete
к команде выше для удаления файлов, который не существует в файле списка. Если Ваша находка не имеет -delete
опция можно использовать rm
с -exec
как следующее:
find /path/to -type f \( ! -name "list" $(printf ' -a ! -name %s\n' $(< list)) \) -exec echo rm {} \;
Или использование -exec
с +
разделитель вместо этого.
find /path/to -type f \( ! -name "list" $(printf ' -a ! -name %s\n' $(< list)) \) -exec echo rm {} +
echo
просто привык к пробному прогону.
Мое предложение:
sed -e 's/^/\.\//' dont-delete.txt > dont-delete-relative-path.txt
find . -type f -print | grep -Fxvf dont-delete-relative-path.txt | xargs -d'\n' rm
Обновление 07.08.2018
Пример:
1: mkdir /tmp/delete-example && cd /tmp/delete-example
2: touch a b c d
3: echo "./a\n./b\n./dont-delete.txt\n" > dont-delete.txt
4: find . -type f -print | grep -Fxvf dont-delete.txt | xargs -d'\n' rm
Отметьте после строки 3, Вы будете иметь dont-delete.txt
файл с содержанием:
./a
./b
./dont-delete.txt
(продвижение ./
очень важно),
Файлы c
и d
будет удален.
Если вывод ls /home/me/myfolder2tocleanup/
превышает максимальный предел аргумента оболочки ARG_MAX
который составляет приблизительно 2 МБ для Ubuntu, я предложил бы следующее.
Одна строка управляет реализацией, которая сделает задание, был бы следующие:
dont-delete.txt
файл к каталогу, содержащему файлы, которые будут удалены как так:cp dont-delete.txt /home/me/myfolder2tocleanup/
cd
к каталогу, содержащему файлы, которые будут удалены как так:cd /home/me/myfolder2tocleanup/
ls -p | grep -v / | sed 's/\<dont-delete.txt\>//g' | sort | comm -3 - <(sort dont-delete.txt) | xargs echo | tr " " "\n"
ls -p | grep -v / | sed 's/\<dont-delete.txt\>//g' | sort | comm -3 - <(sort dont-delete.txt) | xargs rm
Explaination:
ls -p
перечислит все файлы и каталоги в текущем каталоге и опции-p
добавит a/
к именам каталогов.grep -v /
исключит каталоги путем удаления всех объектов, содержащих a/
на их имена.sed 's/\<dont-delete.txt\>//g'
исключитdont-delete.txt
файл, таким образом, это не становится удаленным в процессе.sort
будет, только чтобы удостовериться, отсортировать остающийся выводls
.comm -3 - <(sort dont-delete.txt)
отсортируетdont-delete.txt
файл, сравните его с отсортированным выводомls
и исключите имена файлов, которые существуют в обоих.xargs rm
удалит все остающиеся имена файлов в уже обработанном выводеls
. Это означает, что все объекты в текущем каталоге будут удалены за исключением каталогов, файлы, перечисленные вdont-delete.txt
файл иdont-delete.txt
сам файлВ части пробного прогона:
xargs echo
распечатает файлы, которые должны быть удалены.tr " " "\n"
переведет пробелы в новые строки для более легкой удобочитаемости.