Как скопировать скрытые (начиная с точки) файлы и подкаталоги в linux?

10

Как скопировать скрытые файлы и скрытые подкаталоги (начиная с точки) в папке A в папку B? Например, если у меня есть эта структура:

A/a
A/b
A/.a
A/.b/
A/.b/somefile
A/.b/.c

Я хотел бы скопировать в B только скрытые файлы и скрытые подкаталоги в A:

B/.a
B/.b/
B/.b/somefile
B/.b/.c

Я уже попробовал эту команду: cp A/.* Bиз этого другого вопроса суперпользователя . Тем не менее, он не копирует подкаталоги. Также пытался cp -r A/.* B, но он копирует, .поэтому я заканчиваю с точной копией A (включая обычные файлы). Любая помощь приветствуется.

gaboroncancio
источник

Ответы:

16

Пока вы ищете только скрытые файлы и папки на уровне A и не хотите, например,

A/b/.hidden

чтобы быть скопированным, вы должны быть в состоянии использовать это:

cp -r A/.[^.]* B

Это в основном означает копирование всего, что начинается с, .а затем любого символа, кроме того, .который отфильтровывает .и..

Редактировать: удалил -p из команды cp, так как Аскер не указал, что хочет сохранить права собственности, даты и т. Д.

вездесущность
источник
Это работает для имен файлов примеров и каталогов, приведенных в вопросе, но текст вопроса говорит «скрытые файлы и скрытые подкаталоги (те, которые начинаются с точки)», и этот ответ не найдет файлы и каталоги, имена которых начинаются с две точки; например, ..c.
Скотт
Это довольно серьезный случай, но тем не менее законное беспокойство. Я не учел это. Вы можете объяснить это, переключившись на, .*[^.]но тогда вы пропустите файлы, которые заканчиваются на .. Я думаю, что вам действительно понадобится расширенная глобализация, чтобы действительно учесть все случаи.
Вездесущность
4

Проблема в A/.*том, что существует каталог, .в Aкотором также соответствует шаблону.

Вы можете включить расширенные шаблоны глобусов и использовать следующее:

shopt -s extglob
cp -r A/.!(?(.)) B    

Он соответствует файлам, имя которых начинается с точки, а второй символ не является ни точкой, ни ничем (? (.) Ничего не соответствует или точка,! (...) отрицает его, т.е.! (? (.)) Соответствует всему остальному чем ничто или точка).

choroba
источник
+1 за правильный ответ. Обратите внимание, что .!(@(|.))(AFAICT) эквивалентен приведенному выше, (IMNSHO) немного понятнее, и только на один символ длиннее.
Скотт
3

Для таких случаев рекомендуется использовать findвместо cpэтого:

find A/ -type f -maxdepth 1 -name '.*' -exec cp -p {} B/ \;

Основной синтаксис разбивается следующим образом:

  • find A/ -type f: findэлементы в каталоге A/, тип которых является файлом (вместо каталога)…
  • -maxdepth 1 -name '.*': Для этого maxdepthиз 1 каталогов и чей nameначинается с ..
  • -exec cp -p {} B/ \;И как только эти файлы найдены, команда с флагом для сохранения даты / времени из источника ( ) до пункта назначения .execcp-p{}B/

Мне нравится использовать, maxdepthчтобы добавить слой контроля, поэтому я не случайно копирую целую файловую систему. Но не стесняйтесь удалить это.

JakeGould
источник
0
 for item in `find A -type d | grep -E "\."` ; do cp -r $item B ; done
  • find A -type d предоставляет рекурсивный список в пределах А только с каталогами
  • grep -E "\." фильтрует каталоги с точкой (т.е. скрытые каталоги)
  • здесь нужна опция -E, потому что без нее она также означает «текущий каталог»
  • обратный слеш должен избегать значения в регулярном выражении «любого символа»
  • cp -r копировать рекурсивно

Я создал структуру файлов и папок для A и выполнил команду в Git Bash (у меня сейчас нет Linux), и это сработало.

malarres
источник
Это ломается, если в файлах есть пробелы или специальные символы в имени или пути.
slhck
Спасибо, что заметили :) На самом деле я ограничился "контрольным примером" @gaboroncancio. Если вы можете дать мне другую тестовую батарею, я могу попытаться улучшить ее (конечно, если вы хотите, улучшите ее самостоятельно, либо отредактировав этот ответ, либо создав новый ответ)
malarres
Вы можете просто поместить точечные файлы в папку с именем A B, и тогда они будут работать неожиданно, потому что они расширятся до cp -r A B/.dotfile B. Общий совет не разбирать findили lsвыводить вообще. Если вы используете, findвы должны также использовать его собственные параметры для фильтрации grep, а если вы передаете findвывод в другое место, используйте -print0или напрямую вызовите нужную команду. Смотрите find руководство .
slhck
В более общем смысле, при работе с файлами безопаснее использовать глобусы оболочки, как объяснено в других ответах (хотя они часто требуют extglobнастройки).
Slhck
Спасибо за ссылку. Давай тогда оставим findразбор.
Malarres
0

В качестве альтернативы вы можете использовать эту другую команду, если второй символ буквенно-цифровой ( источник ):

cp -r A/.[a-zA-Z0-9]* B
gaboroncancio
источник
Это работает для имен файлов примеров и каталогов, приведенных в вопросе, но текст вопроса говорит «скрытые файлы и скрытые подкаталоги (те, которые начинаются с точки)», и этот ответ не найдет файлы и каталоги, имена которых начинаются с точка и специальный символ; например, .@fooили ..c.
Скотт
Вот почему я указываю, что это работает, если второй символ буквенно-цифровой. ;)
gaboroncancio