Рекурсивное удаление дубликатов из другого каталога

ИспользованиеXMLStarlet:

xml sel -t -v '//binariesDir' filestore.xml

в Ubuntu с установленным пакетом xmlstarlet, мне нужно использовать этот:

xmlstarlet sel -t -v '//binariesDir' filestore.xml

2
12.01.2021, 16:51
2 ответа

Следующее найдет все обычные файлы в или ниже ./to_keepи вызовет скрипт в -строке sh -cс их пакетами. Для каждой партии путей скрипт в строке -будет вызывать findодин раз, чтобы найти обычные файлы в ./to_purgeс такими же именами. Пути этих файлов в ./to_purgeбудут напечатаны (, чтобы удалить их, добавьте -deleteпосле-print).

find to_keep -type f -exec sh -c '
    for pathname do
        set -- "$@" -o -name "${pathname##*/}"
        shift
    done; shift
    find to_purge \( "$@" \) -type f -print' sh {} +

или, по запросу, в одну строку:

find to_keep -type f -exec sh -c 'for pathname do set -- "$@" -o -name "${pathname##*/}"; shift; done; shift; find to_purge \( "$@" \) -type f -print' sh {} +

Сценарий строки -строит список операций ИЛИ -из -nameтестов для команды find, которую он использует в своей последней строке. Цикл создает этот список в позиционных параметрах из компонента имени файла каждого пути, который ему передал внешний find.

Это относится ко всем разрешенным именам файлов, включая имена файлов, содержащие пробелы, символы табуляции и символы новой строки. Опять же, чтобы удалить файлы, добавьте-delete(или-exec rm {} +)после -printв коде.

В виде короткого сценария, который принимает «сохранить каталог» и «очистить каталог» в качестве аргументов командной строки:

#!/bin/sh

keepdir=$1
purgedir=$2

find "$keepdir" -type f -exec sh -c '
    dir=$1; shift
    for pathname do
        set -- "$@" -o -name "${pathname##*/}"
        shift
    done; shift
    find "$dir" \( "$@" \) -type f -print' sh "$purgedir" {} +

Единственная проблема с этим кодом заключается в том, что он будет использовать имена в одном каталоге в качестве шаблонов для поиска имен файлов в другом каталоге. Это означает, что если файл в первом каталоге называется *, все файлы во втором каталоге удаляются.Вы можете исправить это, защитив имена файлов во внутреннемfind:

for pathname do
    sane=$( printf "%s\n" "${pathname##*/}" | sed "s/[[*?]/\\&/g" )
    set -- "$@" -o -name "$sane"
    shift
done; shift

Эта модификация цикла в сценарии -строки sh -cэкранирует символы [, *и ?(, которые в противном случае использовались в качестве шаблонов подстановки имен файлов ). Сценарий теперь не будет работать с именами файлов, которые заканчиваются новой строкой (из-за используемой подстановки команд ), но, возможно, с этим можно жить.

1
18.03.2021, 22:37

Типично, не успел написать, как нашел ответ!

find./to_keep/ -type f -exec basename '{}' \; | xargs --max-args=1 find./to_purge/ -name | xargs --max-args=1 rm

Я не приму это как ответ, так как я еще не знаю, что не так с моими предыдущими попытками.

0
18.03.2021, 22:37

Теги

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