Как найти каталоги, содержащие только определенные файлы

Это зависит от того, что вы подразумеваете под переустановкой. Чтобы просто переустановить:

pacman -S python python2

Если вы имеете в виду очистку системы, то переустановка pacman -Rns python python2скорее всего не сработает, потому что у вас будут пакеты, зависящие от них. Если вы все еще хотите это сделать, вы можете, но на всякий случай:

  1. Убедитесь, что ваша система обновлена ​​-до -даты(pacman -Syu).
  2. Загрузите пакеты Python, чтобы убедиться, что они находятся в кеше:pacman -Sw python python2.
  3. Закройте все запущенные приложения.
  4. Выйдите из сеанса, если вы используете WM или DE.
  5. Войдите в TTY, остановите все службы, которые не требуются.
  6. Выполнить pacman -Rddn python python2.
  7. Выполнить pacman -S python python2. Вероятно, вы также захотите указать --asdeps.

При этом весь этот процесс вряд ли принесет что-то большее, чем первая, гораздо более безопасная команда.

4
13.08.2019, 16:54
5 ответов

Вам нужно будет указать файлы или папки, в идеале по имени, например:

find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty rm

найдет все файлы(-type f)с именем(-iname)"thumbs.db" (, игнорируя регистр из-за iв iname), а затем удаляя(rm)их.

Вы можете использовать шаблоны имен файлов, например.

find ${HOME} -type f -iname '*.tmp' -print0 | xargs -0 --no-run-if-empty rm

Предупреждение:Будьте внимательны при вводе, удаление может произойти без вашего ведома.

Делайте регулярные резервные копии -прямо перед тем, как приступить к очистке, это может быть хорошим моментом!

Если вы хотите узнать, что произойдет, сначала посмотрите список файлов, прежде чем rmчто-либо писать, например:

find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty ls -l
3
27.01.2020, 20:45

Использовал эту комбинацию команд find, xargs, ls, sed, wc и awk, и она работает:

find. -type f \( -iname "desktop.ini" -o -name "thumb.db" \)  -printf %h\\0 | xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}" | sed -n "1!p" | wc -l' | awk '$2 == "1" {print $0}'

Пояснение:

  • find.найти в текущем каталоге
  • -type fнайти только файлы
  • \( -iname "desktop.ini" -o -name "thumb.db" \)где имя файла "desktop.ini" или "thumb.db" без учета регистра
  • printf %h\\0вывести начальный каталог имени файла + ASCII NUL
  • xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}"распечатать выходной каталог и выполнить ls -lдля каждого из них
  • sed -n "1!p" | wc -l'исключить первую строку из ls -l, содержащую общее количество файлов и каталогов, а затем подсчитать строки
  • awk '$2 == "1" {print $0}'вывести строку, если только count равен "1"
4
27.01.2020, 20:45

Чтобы найти все каталоги, которые не содержат других имен, кроме *.tmp, desktop.ini, Thumbs.dbи/или.picasa.ini:

find. -type d -exec bash -O dotglob -c '
    for dirpath do
        ok=true
        seen_files=false
        set -- "$dirpath"/*
        for name do
            [ -d "$name" ] && continue  # skip dirs
            seen_files=true
            case "${name##*/}" in
                *.tmp|desktop.ini|Thumbs.db|.picasa.ini) ;; # do nothing
                *) ok=false; break
            esac
        done

        "$seen_files" && "$ok" && printf "%s\n" "$dirpath"
    done' bash {} +

Это будет использовать find, чтобы найти любые каталоги ниже текущего каталога (, включая текущий каталог ), и передать их сценарию оболочки.

Сценарий оболочки перебирает указанные пути к каталогам и для каждого из них расширяет *в нем (с параметром оболочки dotglob, установленным в bash, для обнаружения скрытых имен ).

Затем он просматривает список полученных имен и сопоставляет их с конкретными шаблонами и именами, которые мы хотели бы найти, (игнорируя каталоги ). Если он находит любое другое имя, которое не соответствует нашему списку, он устанавливает okвfalse(вместоtrue)и выходит из этого внутреннего цикла.

Переменная seen_filesстановится true, как только мы видим файл любого типа, кроме каталога(или символической ссылки на каталог). Эта переменная помогает нам не сообщать о подкаталогах, которые содержат только другие подкаталоги.

Затем он запускает $seen_filesи$ok(trueили false), и если они оба true, это означает, что каталог содержит по крайней мере один обычный файл, а содержит только имена файлов из нашего списка . ], он печатает путь к каталогу.

Вместо

set -- "$dirpath"/*
for name do

вы, очевидно, могли бы

for name in "$dirpath"/*; do

вместо этого.

Тестирование:

$ tree
.
`-- dir
    |-- Thumbs.db
    `-- dir
        |-- file.tmp
        `-- something

2 directories, 3 files
Здесь запускается команда

(find, выводящая результат...)

./dir

Это означает, что каталог ./dirсодержит только имена из списка (, игнорируя каталоги ), а ./dir/dirсодержит и другие вещи.

Если удалить [ -d "$name" ] && continueиз кода, каталог ./dirне будет найден, так как он содержит имя (dir), которого нет в нашем списке.

9
27.01.2020, 20:45

С zsh,ты можешь сделать

set -o extendedglob # for ^ and (#i)

printf '%s\n' **/*(D/F^e'[()(($#)) $REPLY/^(#i)(*.tmp|desktop.ini|Thumbs.db|.picasa.ini)(ND)]')

Список каталогов, содержащих только записи, соответствующие (*.tmp|desktop.ini|Thumbs.db|.picasa.ini)без учета регистра.

  • **/:рекурсивный глобус (любой уровень подкаталогов)
  • *(qualifier):glob (здесь *соответствие любому файлу )с квалификаторами (для соответствия другим критериям, кроме имени ).
  • D:включить dotglobдля этого шара (включить скрытые файлы и просмотреть скрытые каталоги ).
  • /:выбирать только файлы типа директория
  • F:только те Fпустые (, которые содержат хотя бы одну запись ). Удалите, если вы также хотите перечислить пустые каталоги.
  • ^:отрицание следующих квалификаторов
  • e'[code]':квалификатор оценки e:выбирает файлы, для которых код не (с предыдущим^)возвращает true.
  • () {code} args:анонимная функция. Здесь код (($#))представляет собой арифметическое выражение в стиле ksh -, которое здесь оценивается как true, если $#не равно -нулю ($#, являющемуся количеством аргументов анонимной функции ).
  • $REPLY/^(#i)(*.tmp|desktop.ini|Thumbs.db|.picasa.ini)(ND)составляет аргументы этой встроенной функции. Вот еще один шар:
  • $REPLY:внутри e'[code]'— это путь к рассматриваемому в данный момент файлу.
  • ^:отрицание.
  • (#i):включить нечувствительное к регистру сопоставление для остальной части шаблона.
  • (*.tmp|desktop.ini|Thumbs.db|.picasa.ini):любой из тех, поэтому с отрицанием ни один из них.
  • (ND):еще один квалификатор глобуса. Nдляnullglob(глобус расширяется до нуля, если совпадений нет, поэтому (($#))снова становится ложным ), Dдля dotglob. Здесь, в качестве оптимизации, мы могли бы также добавитьoNNили oк списку соответствующих файлов )и [1], чтобы выбрать только первый, поскольку нам не нужно знать, сколько их есть, только есть ли они вообще.

Чтобы сделать текст более разборчивым,мы могли бы использовать функцию:

set -o extendedglob

has_useful_entries()
  ()(($#)) ${1-$REPLY}/^(#i)(*.tmp|desktop.ini|Thumbs.db|.picasa.ini)(NDoN[1])

printf '%s\n' **/*(D/F^+has_useful_entries)
2
27.01.2020, 20:45
find ~/ -type f -print0 2>/dev/null | 
  awk -F/ 'BEGIN {RS=ORS="\0"};
           {
             d=gensub("/[^/]*$","",1);
             seen[d]++;
             if ($NF ~ /\.tmp$|^(desktop\.ini|Thumbs\.db|\.picasa\.ini)$/) {
               found[d]++;
             };
           };
           END {for (d in seen) { if (seen[d] == found[d]) {print d}}}' 

Это использует findдля вывода списка файлов (и только файлов,-type f)завершающихся NUL -в целевом каталоге или ниже него (~/), и направляет их в сценарий awk. 2>/dev/nullпозволяет избавиться от предупреждающих сообщений из find, если/когда у пользователя нет разрешения спускаться в некоторые подкаталоги -.

Сценарий awk использует /в качестве разделителя полей и устанавливает для разделителей записей ввода (RS )и вывода (ORS )значение NUL. Он извлекает часть имени файла, относящуюся к каталогу, из входной записи и подсчитывает количество просмотров этого каталога (, используя ассоциативный массивseen). Затем, если конечное поле ($NF )совпадает с одним из желаемых шаблонов имени файла, он ведет подсчет совпадений (с использованием ассоциативного массиваfound).

Как только все вводные данные обработаны, он выводит каждый каталог, где количество просмотров каталога равно количеству найденных совпадений для этого каталога.

т. е. он печатает только каталоги, содержащие ТОЛЬКО совпадающие файлы.

Поскольку ORS имеет значение NUL, ее выходные данные можно безопасно использовать в качестве входных данных для xargs -0r rm -rfили аналогичной команды без риска возникновения проблем из-за пробелов, переводов строк или других проблемных метасимволов оболочки -в каталоге. имена.

Вывод может быть дополнительно обработан любым инструментом или языком сценариев, которые могут работать с вводом, разделенным NUL -, включая perlи версии GNU sed, sort, grep, head., tailи многие другие. Во многих случаях вам, вероятно, лучше либо настроить параметры find, либо выполнить дополнительную обработку в сценарии awk(, либо просто переписать все это в perlс помощью модуля File::Find).

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

Наконец, если вы хотите визуально изучить вывод (, например. чтобы убедиться, что вы не собираетесь удалять что-либо важное ), измените строку RS=ORS="\0"на RS="\0", чтобы вы получили строку -между каждым именем каталога. Это нельзя безопасно использовать в качестве ввода для xargs, потому что строки -являются допустимыми символами в именах файлов/каталогов unix.

0
27.01.2020, 20:45

Теги

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