Разница копии содержимого папки между /. и / * в Linux

8

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

cp -rfva ../foldersource/. ./

но это тоже работает

cp -rfva ../foldersource/* ./

есть ли разница?

Например, если я хочу удалить содержимое из папки с. :

rm -rf ../foldersource/.

я получаю ошибку:

rm:  rejet delete folder '.' or '..':

но со звездочкой все в порядке

rm -rf ../foldersource/*

Итак, звездочка - лучшие варианты, которые работают где угодно?

stackdave
источник

Ответы:

10

Существует фундаментальная разница между этими двумя формами аргументов. И важно понять, что происходит.

При ../foldersource/.этом аргумент передается без изменений в команду, будь то cpили rmили что-то еще. Это зависит от команды, имеет ли эта конечная точка особую или уникальную семантику, отличающуюся от стандартного соглашения Unix простого указания на каталог, в котором она находится; и то rmи другое, cpкажется, рассматривает это как особый случай.

С ../foldersource/*аргументом сначала раскрывается оболочкой, прежде чем команда когда-либо будет выполнена и передана какие-либо аргументы. Таким образом, rmникогда не видит ../foldersource/*; он видит расширенную версию ../foldersource/file1.ext ../foldersource/file2.ext ../foldersource/childfolder1и так далее. Это важно, потому что операционные системы ограничивают количество аргументов, передаваемых команде, обычно всего несколько сотен.

eestrada
источник
4
It's up to the command whether that trailing dot makes any senseХм, точка всегда ссылается на сам каталог, в котором она находится, поэтому она ../foldersource/.не должна отличаться от описания ./foldersource/и, фактически, это просто избыточный способ заявить одно и то же. Ни одна команда не пытается «разобраться» с точкой или двойной точкой, поскольку они являются стандартными в файловых системах Linux / Unix. rmпросто отклоняет удаление текущего рабочего каталога, как jimmijуказано в их ответе. Кроме того, обратите внимание, что вы используете ./во всех своих примерах, в то время как OP есть ../там. Отчасти (большая) разница.
Сергей Колодяжный
«cp -rfva ../foldersource/. ./» эквивалентен «cp -rfva ../foldersource ./», я хочу скопировать содержимое папки, но не корневой каталог
stackdave
1
@Stackdave нет, cp -rfva ../foldersource/. ./ НЕ эквивалентно cp -rfva ../foldersource ./ . Трейлинг /.значительный
роайма
2
Несмотря на то, что в этом ответе сказано правильно, в нем отсутствует очень важное различие, как упомянуто в ответе @ roaima: вариант / * (обычно) не копирует файлы или каталоги, начинающиеся с.
Адам
@SergiyKolodyazhnyy Вы правы; .является стандартной конвенцией в Unix для обозначения тока непосредственно. Кроме того, спасибо за указание, что я использовал ./в своих примерах, когда я должен был использовать ../; Я исправлю это. Вы не правы относительно того, имеют ли команды смысл в конце; как точки OP вне (и я испытал с cp) , как rmи cpвести себя по- другому , когда замыкающая .присутствует. Я должен был написать что-то вроде: «Это зависит от команды, если конечная точка имеет особую или уникальную семантику». Я изменю свой ответ для ясности.
Эстрада
10

При копировании с использованием cp -a source/* target/вы копируете большинство файлов и каталогов из sourceв target. В частности, исключаемые элементы, вероятно, будут файлами, начинающимися с точки ( .) на верхнем уровне source.

Рассмотрим эти файлы (или каталоги) в source

apple        # will be copied
banana/      # will be copied, as will all its contents
.cherry      # will not be copied

При копировании с использованием cp -a source/. target/вы копируете все содержимое source, включая любые элементы, начинающиеся с точки ( .), вtarget

Рассмотрим эти файлы (или каталоги) в source

apple        # will be copied
banana/      # will be copied, as will all its contents
.cherry      # will be copied

Если вы используете bash, zshвы можете использовать эту dotglobопцию, чтобы изменить значение *так, чтобы она включала файлы и каталоги, начинающиеся с точки ( yashтакже есть dotglobопция; однако она затем включает .и ..в глобальные расширения, которые ограничивают ее удобство использования. См. Также FIGNORE='@(.|..)'в ksh93)

Интересно, cp -a source/. target/что гарантированно никогда не будет создан компонент target/source. (С другой стороны, cp -a source target/будет делать одно из двух в зависимости от того, существует он или нет target. См. Как рекурсивно копировать папку идемпотентным способом, используя cp для деталей.)


При удалении с помощью вы удаляете rm -rf source/*файлы и каталоги внутри, sourceкоторые не начинаются с точки ( .). С учетом dotglobнастроек, которые я уже упоминал. Он не удалит сам каталог source.

Когда вы попытаетесь удалить rm -rf source/.его, он потерпит неудачу - как уже объяснили другие - потому что POSIX запрещает удаление пути, последний компонент которого .или ... Ближайшим эквивалентом является rm -rf sourceудаление sourceкаталога и всего его содержимого независимо от того, начинаются они с точки или нет ..

roaima
источник
1
Смотрите также. Удаляет ли когда-нибудь 'rm. *' Родительский каталог? о rm -rf .неудаче .
Стефан
7

Вы не можете этого сделать, rm -rf ../foldersource/.потому rmчто не допускаете этого, как явно указано в руководстве:

Любая попытка удалить файл с последним компонентом имени файла '.' или «..» отклоняется без каких-либо подсказок, как того требует POSIX.

и в руководстве по POSIX man 1p rmмы видим:

Если любой из файлов точка или точка-точка указана в качестве части базового имени операнда (то есть конечного компонента имени пути) или если операнд преобразуется в корневой каталог, rm должен записать диагностическое сообщение в стандартную ошибку и ничего не делать больше с такими операндами.

jimmij
источник