Какова дополнительная ценность опции -T в GNU cp и mv?

26

Почему некоторые команды GNU Coreutils имеют -T/--no-target-directoryопцию? Кажется, что все, что он делает, может быть достигнуто с помощью семантики .(собственной точки) в традиционной иерархии каталогов Unix.

Принимая во внимание:

cp -rT /this/source dir

Эта -Tопция предотвращает создание копии dir/sourceподкаталогом. Скорее /this/sourceидентифицируется с dirи содержимое отображается между деревьями соответственно. Так, например, /this/source/foo.cидет dir/foo.cи так далее, а не к dir/source/foo.c.

Но это может быть легко достигнуто без использования -Tопции:

cp -r /this/source/. dir  # Probably worked fine since dawn of Unix?

Семантически компонент задней точки копируется как дочерний элемент dir, но, конечно, этот «дочерний элемент » уже существует (поэтому его не нужно создавать) и фактически является dirсамим собой, поэтому эффект /this/pathидентифицируется с dir.

Это работает нормально, если текущий каталог является целью:

cp -r /this/tree/node/. . # node's children go to current dir

Есть ли что-то, что вы можете сделать только с этим, -Tчтобы рационализировать его существование? (Помимо поддержки операционных систем, которые не реализуют каталог точек, обоснование, не упомянутое в документации.)

Разве вышеприведенный точечный фокус не решает те же условия гонки, о которых говорится в документации GNU Info -T?

Kaz
источник

Ответы:

29

Ваш .трюк может быть использован только когда вы копируете каталог, а не файл. -TОпция работает как с каталогами и файлами. Если вы делаете:

cp srcfile destfile

и уже есть каталог с именем, в который destfileон будет копироваться destfile/srcfile, что может быть не предназначено. Итак, вы используете

cp -T srcfile destfile

и вы правильно получаете ошибку:

cp: cannot overwrite directory `destfile' with non-directory

Если вы попытаетесь использовать .метод, копия никогда не будет работать:

cp: cannot stat `srcfile/.`: Not a directory
Barmar
источник
.Трюк делает работу при копировании файла, только не при переименовании его базового имени в то же время! cp /path/to/file /target/dir/. Если /target/dir/fileсуществует и является каталогом, вы получаете такую ​​же диагностику! Но вы показали -T, что нельзя сделать без него за один шаг, без условий гонки: скопируйте файл и измените его имя, не передавая его в подкаталог.
Каз
3
Это не то же самое - .уловка, о которой вы говорите, заключается в добавлении /.к источнику .
Бармар
21

Проблема с cp/ mv/, lnпоскольку они были изначально разработаны, состоит в том, что они представляют собой две команды в одной ( копировать в и копировать в ).

cp A B

это либо копирование A в B, либо копирование A в B ( копирование A в B / A ) в зависимости от того, Bсуществует ли и является ли каталог каталогом или нет (и больше вариантов, если B является символической ссылкой на каталог).

Это плохо, потому что это неоднозначно. Таким образом, реализации GNU добавили варианты, чтобы обойти это.

cp -T A B

копии от А до Б независимо. Если Bсуществует и является каталогом, это не удастся (если вы не пройдете -r). В любом случае вы не получите Aфайл внутри, Bесли вы намеревались Aскопировать его в B.

А также:

cp -t B A

это копия в .

Стефан Шазелас
источник
Оригинальная философия Unix предполагает, что вы знаете, что делаете, и с радостью позволит вам выстрелить себе в ногу.
Ленн
4
@ Ленн, но здесь это не дает тебе способа избежать попадания в ногу. Если кто-то создаст каталог B или символическую ссылку на какой-либо каталог непосредственно перед тем, как вы запустите cp A Bкоманду, она не сделает то, что вы хотели. И в действии [ -e B ] || [ -L B ] || cp A Bвсе еще есть состояние гонки, которого cp -Tn A Bнет.
Стефан Шазелас
6

-TМожет обеспечить провал , если каталог неправильно существует для того, что должно быть файл назначения:

$ mkdir mustbeafile
$ touch afile
$ cp -T afile mustbeafile
cp: cannot overwrite directory `mustbeafile' with non-directory
$ echo $?
1
$ cp afile mustbeafile
$ 

То есть вместо успешного завершения при неожиданном копировании в подкаталог возникает предупреждение и плохой статус выхода, что может привести к прерыванию работы сценария, и человек проверяет, почему существует каталог, в котором его не должно быть. Будь один.

thrig
источник
0

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

rackandboneman
источник