Як скопіювати назву файла, починаючи з крапки?


26

Я намагаюся скопіювати всі файли з каталогу A у каталог B. Усі файли в каталозі A починаються з крапки, наприклад:

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

яку я виявив, якщо використовую:, cp A/* Bзавжди отримую помилку:

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

Здається, немає варіанту, cpяк lsобробляти записи, розпочаті з крапки, хтось має ідею, як це виправити?

Відповіді:


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

Це лише проблема, якщо ви використовуєте -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, ви повинні прочитати питання ще раз. Усі файли в. AПриховано. Він просто хоче це скопіювати.

7

Що ви шукаєте, це більше:

cp A/.??* B/

Це відповідатиме всім точковим файлам, але не "". або "..". Більшість перерахованих вище рішень є прекрасними, якщо ви не працюєте рекурсивно. Але як тільки ви захочете зробити щось на кшталт:

cp -R A/.??* B/

Не опускаючи "..", ви скопіюєте все з батьківського каталогу вниз, у тому числі нетотлові файли.


1
При цьому будуть пропущені крапки-файли, які є одним символом, як-от .aабо .x. Я виявив найкоротший шаблон глобалізації, який відповідає кожному точковому файлу, крім .і ..є .[^.]*.
павон

2

Я прислухався, спробував наступне, і це працює просто знайти ...

cp A/.* B/

2
Це також перейде A/.і A/..як параметри cp, що може бути проблематичним у випадку, якщо ОП також потребує копіювання каталогів (з використанням cp -r)
peoro

2

Це не cp«s вина , це Баш: Баш розширює *в усіх без прихованого (тобто не відправною з .) файлів.

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

Простим рішенням може бути видалення .та ..з файлів, які відповідають .*, (дуже) шалений спосіб, як цей:

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

або цей (можливо, чистіший: він використовує findдля пошуку файлів для копіювання):

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

але ви, швидше за все, знайдете більш чисті рішення.


чому ви повинні використовувати a, 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); зробіть cp -R "$ act" B; зроблено



0

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

Це безпечно:

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

0

Це стара нитка ... але мені завжди вдавалося копіювати всі файли. У тому числі файли / папки, які починаються з "."

Приклад копіює всі файли та папки:

cp -aup /root/.* / резервна копія / root /

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.