Как скопировать файл с именем, начинающимся с точки?

26

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

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

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

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

Кажется , что нет никакой возможности для , cpкак lsк ручке записи началась с точкой, у кого есть идеи , как это исправить?

user59285
источник

Ответы:

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
Mikel
источник
Это только проблема, если вы используете -r. Без -rэтого он просто пропустит каталоги.
Микель
И пример, который я -Rпривожу, тоже должен работать. Если вы считаете, что это неправильно, объясните, пожалуйста, почему.
Микель
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

источник
Использование dotglob OP также скопирует все не скрытые файлы, а это не то, что он хочет.
peoro
@peoro, ты должен прочитать вопрос снова. Все файлы в Aскрыто. Он просто хочет скопировать это.
7

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

cp A/.??* B/

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

cp -R A/.??* B/

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

Джон Вестлунд
источник
1
Это пропустит точечные файлы, состоящие из одного символа, например .aили .x. Самый короткий шаблон поиска, который я нашел, соответствует каждому файлу точек, кроме .и ..есть .[^.]*.
павон
2

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

cp A/.* B/
Андрей Белый
источник
2
Это также будет передаваться A/.и в A/..качестве параметров cp, что может быть проблематично, если OP также необходимо скопировать каталоги (используя cp -r)
peoro
2

Это не cp«s вина , это Баш: Баш расширяет *во всех без скрытого (т.е. не отправной с .) файлов.

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

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

peoro
источник
почему вы должны использовать, for loopа затем создать дополнительный grepпроцесс, чтобы сделать работу, как cp A/.*? cpбудет игнорировать "." и ".." каталоги.
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
AmitP
источник
0

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

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

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

Ontologik
источник