23

Я пытаюсь скопировать все файлы в каталоге A в каталог B. Все файлы в каталоге A начинаются с точки, например:

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

который я нашел, если я использую: cp A/* B , всегда получаю ошибку:

cp: cannot stat 'A/*': no such file or directory

Кажется, у cp нет опции, так как ls обрабатывает записи, начинающиеся с точки, у кого-нибудь есть идеи, как это исправить?

10 ответов10

34

Причина в том, что в bash * не включены файлы, начинающиеся с точки (.).

Вы можете запустить

cp A/.* B

Он предупредит вас, что не скопировал . или .. , или любые подкаталоги, но это нормально.

Или, если вы хотите скопировать точечные и обычные файлы вместе, запустите

cp A/.* A/* B

Вы также можете запустить

shopt -s dotglob
cp A/* B

который будет работать в bash , но не sh .

И если вы не возражаете против копирования подкаталогов, то это самое простое:

cp -R A/ B

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

$ echo A/*
A/file1 A/file2

$ echo A/.*
A/. A/.. A/.hidden1 A/.hidden2

$ echo A/.* A/*
A/. A/.. A/.hidden1 A/.hidden2 A/file1 A/file2

$ shopt -s dotglob
$ echo A/*
A/file1 A/file2 A/.hidden1 A/.hidden2
7

Если bash, вы можете установить dotglob перед копированием

shopt -s dotglob
cp A/* /destination

Или язык программирования

$ ruby -rfileutils -e  'Dir[".*"].each {|x| FileUtils.copy(x,"/destination") if File.file?x}'

Если вы не хотите устанавливать dotglob, просто

cp A/.* /destination 2>/dev/null
5

То, что вы ищете, больше похоже на:

cp A/.??* B/

Это будет соответствовать всем точечным файлам, но не "." или же "..". Большинство из приведенных выше решений хороши, если вы не работаете рекурсивно. Но как только вы захотите сделать что-то вроде:

cp -R A/.??* B/

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

2

Я просто попробовал следующее, и это работает, просто найти ...

cp A/.* B/
2

Это не ошибка cp , это bash: bash раскрывает * во всех не скрытых (то есть: не начинающихся с .) Файлах.

Bash расширится . * (Таким образом, .* A/.* , в вашем случае) со всеми файлами, начинающимися с . , но, к несчастью, это также включает в себя . и .. (текущий и родительский каталоги), которые вы, вероятно, захотите пропустить. (Обратите внимание, что другие оболочки, такие как zsh, не будут включать их, и IIRC также bash, после установки некоторых параметров).

Простое решение может быть удалить . и .. из файлов, сопоставленных с .* , (очень) хакерским способом, как этот:

cp $( for F in A/.*; do echo $F | grep -v "^\.*$"; done ) B

или этот (вероятно, более чистый: он использует find чтобы найти файлы для копирования):

cp $( find A -maxdepth 1 -mindepth 1 -name ".*" ) B

но вы, вероятно, найдете более чистые решения.

1

Если они все начинаются с точки, просто используйте A/.*:

[holt@Michaela test]$ cp A/* B
cp: cannot stat `A/*': No such file or directory

[holt@Michaela test]$ cp A/.* B
cp: omitting directory `A/.'
cp: omitting directory `A/..'
[holt@Michaela test]$ ls -al B
total 8
drwxrwxr-x. 2 holt holt 4096 2011-03-31 16:57 .
drwxrwxr-x. 4 holt holt 4096 2011-03-31 16:57 ..
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .a
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .b
-rw-rw-r--. 1 holt holt    0 2011-03-31 16:57 .c

Надеюсь это поможет!

1

Вы можете использовать этот скрипт

IFS = $ '\n'; для действия в $(найти A -d 1); do cp -R "$ act" B; сделанный

0

копия:

cp A/.* B

список:

ls -l A/.*

список файлов без нисходящих каталогов:

ls -ld A/.*
0

Вы должны исключить. и .. из списка файлов, переданных в cp!

Это безопасно:

ls -1d A/.[a-zA-Z]* | xargs -i cp -rp {} B
0

Это старая ветка ... но мне всегда удавалось копировать все файлы. Включая файлы / папки, начинающиеся с '.'

Пример скопирует все файлы и папки:

cp -aup /root/.* /backup /root /

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .