Это, вероятно, довольно легко, но каков наилучший способ рекурсивного переименования всех каталогов с именем "A" в "B" ниже базового каталога без использования символических ссылок и объединения содержимого конфликтующих каталогов вместе? То есть, если каталог "B" уже существует, то содержимое "A" следует переместить в "B", а пустой каталог "A" удалить.
1 ответ
Нет единой программы, которая выполняет функцию переименования / слияния, хотя mv ... -t ...
было бы полезно, если бы ее было легче использовать в команде find
. Итак, что я разработал:
find BaseDir/ -type d -name "A" | sort -r | while read d; \
do [ -d "${d%A}B" ] && mv "$d"/* "${d%A}B"/ && rmdir "$d" || \
mv "$d" "${d%A}B"; done
Что это делает:
- Найти все каталоги с именем
A
- Выполните обратную сортировку, чтобы, например,
BaseDir/A/A
был переименован передBaseDir/A
: если последний был переименован первым, первый не будет найден впоследствии. - Пройдите по каждому найденному каталогу: если
B
не существует, работает простое переименование; в противном случае содержимоеA
перемещается вB
и теперь пустоеA
можно удалить.
Обратите внимание, что если B
уже существует, любые файлы, которые он содержит, будут перезаписаны файлами с таким же именем в A
: вы можете добавить дополнительные команды, чтобы предотвратить это - вы можете использовать mv -i
, но вам нужно будет восстановить терминал для любого запроса (например, mv </dev/stdin -i ...
или что-нибудь, что поддерживает ваш Linux), так как stdin
был перенаправлен в сценарий.
Я использовал кавычки, чтобы учесть пробелы в любом из элементов пути, включая A
и B
Я пытался протестировать различные иерархии, но не уверен, что охватил все структуры, которые вы могли бы использовать. Я предлагаю сначала поставить echo
перед командами mv
и rmdir
, пока вы не убедитесь, что команда делает то, что вам нужно.