cp приховані файли з глобальними візерунками


13

Ситуація:

$ mkdir foo && touch foo/.test
$ cp foo/* .
zsh: no matches found: foo/*
(or bash : cp: cannot stat foo/*’: No such file or directory)

У мене каталог, який повно прихованих папок і файлів. Що відбувається і яке рішення?


dotglobтранслюються globdotsпо Zsh , яка неприпустиме ім'я опції для Баша .

Відповіді:


19

Відмова: Ця відповідь стосується Bash конкретно, але значна частина стосується питання щодо глобальних моделей!

Зоряний персонаж ( *) - це майна. Існує певний набір символів, який він займе місце, і перший символ, який є крапкою ( .), не є одним з них. Це особливий випадок саме тому, як працюють файлові системи Unix, файли, які починаються з крапки, вважаються "прихованими". Це означає, що такі інструменти, як cp, lsі т. Д., Не будуть "бачити" їх, якщо прямо не вказано.

Приклади

Спершу давайте створимо деякі зразкові дані.

$ mkdir .dotdir{1,2} regdir{1,2}
$ touch .dotfile{1,2} regfile{1..3}

Отже, тепер ми маємо наступне:

$ tree -a
.
|-- .dotdir1
|-- .dotdir2
|-- .dotfile1
|-- .dotfile2
|-- regdir1
|-- regdir2
|-- regfile1
|-- regfile2
`-- regfile3

Тепер пограємо в кілька ігор. Ви можете скористатися командою, echoщоб перерахувати, що конкретний підстановник ( *) буде для даної команди на зразок:

$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3


$ echo reg*
regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2

$ echo .* *
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

$ echo .dotdir*
.dotdir1 .dotdir2

Зміна поведінки?

Ви можете скористатися командою, shopt -s dotglobщоб змінити поведінку *так, що крім файлів, подібних до regfile1нього, також буде відповідати .dotfile1.

уривок зі bashсторінки man

dotglob If set, bash includes filenames beginning with a `.' in the results 
        of pathname expansion.

Приклад:

$ shopt -s dotglob
$ echo *
.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3

Ви можете повернути цю поведінку за допомогою цієї команди:

$ shopt -u dotglob
$ echo *
regdir1 regdir2 regfile1 regfile2 regfile3

Ваша ситуація?

Для вас ви говорите, cpщо хочете скопіювати всі файли, які відповідають шаблону *, а файлів немає.

$ cp foo/.* .

Або ви можете зробити це, якщо ви хочете, щоб все було в fooпапці:

$ cp foo .

Або ви можете бути явними:

$ cp foot/.* foo/* .

Більш компактна форма із застосуванням розширення дужок у bash:

$ cp foo/{.,}* .

У будь-який час ви можете використовувати echoфокус, щоб побачити запропоновані вами шаблони файлів (це вигадний термін для того, до складу якої належить зірка).

$ echo {.,}*
. .. .dotdir1 .dotdir2 .dotfile1 .dotfile2 abc regdir1 regdir2 regfile1 regfile2 regfile3

До речі, якщо ви збираєтесь скопіювати каталог файлів + інші каталоги, зазвичай це потрібно зробити рекурсивно, це -Rперехід до cp:

$ cp -R foo/. .

1
Ви можете згадати про використання shopt -s dotglob, echo *а потім дає:.dotdir1 .dotdir2 .dotfile1 .dotfile2 regdir1 regdir2 regfile1 regfile2 regfile3
Drav Sloan

@DravSloan - дякую за пропозицію. Додав.
slm

cp -r foo .зазвичай не працюватиме, оскільки cpвідмовиться копіювати fooнад собою, ви, мабуть, мали на увазі cp -R foo/. .. (зверніть увагу, що cp -Rце стандарт).
Стефан Шазелас

1
Також зауважте, що (досить розумно), zshне включає .і ..в розширення .*. В zsh, якщо шаблон не відповідає, то команда переривається (цілком здраво знову), так що в загальному випадку, cp foo/{,.}* .НЕ вийде, якщо ні не приховано або нет не-прихованих файлів.
Стефан Шазелас

7
Ця відповідь стосується лише bash. Запитувач використовує zsh, де відповідь набагато простіше і shoptне існує.
Жил "ТАК - перестань бути злим"


4

Оболонка розглядає ці файли як приховані, коли вона вирішує *символ, тому cpне отримує жодне з цих імен файлів як аргументів.

Ви можете скопіювати їх, чітко вказавши cp foo/.* .


1

Якщо ви хочете зробити це скопіювати всі файли та каталоги з одного місця в інше, ви можете використовувати стандартну rsyncкоманду. У наведеному вище прикладі:

mkdir foo && touch foo/.test
rsync -a foo/ .

буде рекурсивно копіювати весь вміст foo, включаючи приховані файли та приховані каталоги, у поточний каталог. Косою косою рисою в кінці foo/є важливим для rsync; з нею fooкопіюється лише вміст , без цього rsync також буде копіювати foo. Наприклад:-

mkdir src && mkdir dest && touch src/.test
rsync -a src  dest    // copies 'src' contents to 'dest/src'
rsync -a src/ dest    // copies 'src' contents to 'dest' 

Існує багато інших варіантів налаштування rsync, включаючи копіювання між машинами.


1

ЗШ Stéphane Chazelas в відповідь є правильним для одного виразу з Glob в ньому. Однак якщо ви хочете встановити його для всіх виразів за замовчуванням, ви можете використовувати

setopt GLOB_DOTS

Покладіть його у своє, ~/.zshrcщоб зробити його постійним.

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