![Определите общие имена подкаталогов в двух разных каталогах и удалите их.](https://rvso.com/image/97237/%D0%9E%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B8%D1%82%D0%B5%20%D0%BE%D0%B1%D1%89%D0%B8%D0%B5%20%D0%B8%D0%BC%D0%B5%D0%BD%D0%B0%20%D0%BF%D0%BE%D0%B4%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2%20%D0%B2%20%D0%B4%D0%B2%D1%83%D1%85%20%D1%80%D0%B0%D0%B7%D0%BD%D1%8B%D1%85%20%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%B0%D1%85%20%D0%B8%20%D1%83%D0%B4%D0%B0%D0%BB%D0%B8%D1%82%D0%B5%20%D0%B8%D1%85..png)
У меня есть два каталога dir1
, dir2
в которых есть сотни подкаталогов в depth 1
. Мне нужна только информация об именах подкаталогов, которые являются общими для dir1
и , dir2
и я систематически удаляю их из dir2
. Мне не нужно сравнивать файлы или содержимое файлов. Выполнение
diff -qr dir_one dir_two | sort
также выводит имена файлов, которые меня в данный момент не интересуют.
решение1
В вашем случае вы можете избежатьидентифицироватьобщие каталоги, поскольку rm -rf
просто игнорирует несуществующие.
Так что достаточноfind
всекаталоги dir1
и удалить их из dir2
:
find dir1 -mindepth 1 -maxdepth 1 -type d -printf "dir2/%f\0" |xargs -0 rm -rf --
Некоторые пояснения. По умолчанию find
будут выведены все каталоги с полным путем, который равен dir1
. Поэтому мы используем -printf
для вывода только имени файла без ведущих каталогов (%f) плюс другой путь "dir2", где мы хотим удалить. Кроме того, мы завершаем строку нулевым байтом '\0' вместо новой строки, чтобы использовать xarg
опцию -0
, которая делает все это безопасным относительно имен файлов с пробелами. Затем xargs
будет прочитан stdin и выполнена rm
команда, добавлены все строки в качестве аргументов.
Обратите внимание, что перед тем, как удалить их, вы можете проверить свою командную строку, добавив echo
для вывода только rm
команды:
find dir1 -mindepth 1 -maxdepth 1 -type d -printf "dir2/%f\0" |xargs -0 echo rm -rf --
Только длясписокобщие каталоги, которые можно использовать ls
вместо rm
(добавив 2>/dev/null, чтобы игнорировать несуществующие):
find dir1 -mindepth 1 -maxdepth 1 -type d -printf "dir2/%f\0" |xargs -0 -r ls -d -- 2>/dev/null
решение2
comm -1 -3 <( cd dir1 && find -maxdepth 1 -type d | sort ) <( cd dir2 && find -maxdepth 1 -type d | sort ) | ( cd dir2 && xargs rm -rf )
с переносами строк для удобства чтения:
comm -1 -3 <( cd dir1 && find -maxdepth 1 -type d | sort ) \
<( cd dir2 && find -maxdepth 1 -type d | sort ) \
| ( cd dir2 && xargs rm -rf )
объяснение
find -maxdepth 1 -type d
перечислить только каталоги без подкаталогов.
cd dir1 && find -maxdepth 1 -type d | sort
сначала перейдите в каталог, а затем выведите список каталогов.
<( ... )
comm -1 -3 <( ... ) <( ... )
берется первый вход и второй вход и печатаются строки, уникальные для второго входа. По сути, это печатает каталоги, которые есть в , dir2
но не в dir1
.
... | ( cd dir2 && xargs rm -rf )
изменить рабочий каталог, чтобы dir2
затем выполнить команду rm -rf
с выводом предыдущей команды в качестве аргументов. по сути, это приведет к удалению каталогов, которые находятся в , dir2
но не в dir1
.
Сначала выполните проверку, отсоединив трубу xargs
и осмотрев выход.
решение3
find dir1 dir2 -maxdepth 2 | egrep '/' | xargs --max-args 1 basename | sort | uniq -c | egrep -v '^ 1 ' | while read n de ; do echo rm -rfv dir2/$de ; done
уберите эхо, если все правильно.