Jaka jest wartość dodana opcji -T w GNU cp i mv?

26

Dlaczego niektóre polecenia GNU Coreutils mają taką -T/--no-target-directoryopcję? Wydaje się, że wszystko, co robi, można osiągnąć za pomocą semantyki .(self dot) w tradycyjnej uniksowej hierarchii katalogów.

Wobec:

cp -rT /this/source dir

Ta -Topcja zapobiega tworzeniu dir/sourcepodkatalogu przez kopię . Raczej /this/sourcejest identyfikowany z, dira zawartość jest odpowiednio mapowana między drzewami. Więc na przykład /this/source/foo.cchodzi do dir/foo.ci tak dalej, niż do dir/source/foo.c.

Ale można to łatwo osiągnąć bez -Topcji:

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

Semantycznie, kropka końcowa jest kopiowana jako dziecko dir, ale oczywiście to „dziecko” już istnieje (więc nie musi być tworzone) i jest w rzeczywistości dirsobą, więc efekt /this/pathjest identyfikowany z dir.

Działa dobrze, jeśli bieżącym katalogiem jest cel:

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

Czy istnieje coś, co można zrobić tylko z -Tktóre mogą zracjonalizować swoje istnienie? (Poza obsługą systemów operacyjnych, które nie implementują katalogu kropek, uzasadnienie nie zostało wymienione w dokumentacji.)

Czy powyższa sztuczka punktowa nie rozwiązuje tych samych warunków wyścigu, o których mowa w dokumentacji GNU Info -T?

Kaz
źródło

Odpowiedzi:

29

Tej .sztuczki można użyć tylko podczas kopiowania katalogu, a nie pliku. -TOpcja działa zarówno z katalogów i plików. Jeśli zrobisz:

cp srcfile destfile

i już istnieje katalog o nazwie destfile, do destfile/srcfilektórego będzie kopiowany , co może nie być zamierzone. Więc używasz

cp -T srcfile destfile

i poprawnie otrzymujesz błąd:

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

Jeśli spróbujesz użyć tej .metody, kopia nigdy nie zadziała:

cp: cannot stat `srcfile/.`: Not a directory
Barmar
źródło
.Trik robi pracę podczas kopiowania pliku, nie tylko podczas zmiany nazwy jego basename w tym samym czasie! cp /path/to/file /target/dir/. Jeśli /target/dir/fileistnieje i jest katalogiem, otrzymasz taką samą diagnostykę! Ale pokazałeś, czego -Tnie da się zrobić bez niego w jednym kroku, bez warunków wyścigu: skopiuj plik i zmień jego nazwę, bez przetaczania go do podkatalogu.
Kaz
3
To nie to samo - .sztuczka, o której mówisz, polega na dołączeniu /.do źródła .
Barmar,
21

Problem z cp/ mv/ lntak, jak zostały pierwotnie zaprojektowane, polega na tym, że są to dwa polecenia w jednym ( kopiowanie do i kopiowanie do ).

cp A B

to albo kopia A do B, albo kopia A do B ( kopia A do B / A ) w zależności od tego B, czy istnieje i jest katalogiem, czy nie (i więcej odmian, jeśli B jest dowiązaniem symbolicznym do katalogu).

To źle, ponieważ jest niejednoznaczne. Dlatego implementacje GNU dodały opcje obejścia tego.

cp -T A B

niezależnie od tego kopiuje A do B. Jeśli Bistnieje i jest katalogiem, to się nie powiedzie (chyba że zdasz -r). W każdym razie nie będziesz mieć Apliku w środku, Bgdy zamierzasz Azostać skopiowany do B.

I:

cp -t B A

jest kopia do .

Stéphane Chazelas
źródło
Oryginalna filozofia uniksowa zakłada, że ​​wiesz, co robisz, i chętnie pozwoli ci strzelić sobie w stopę.
Lenne
4
@Lenne, ale tutaj nie daje to sposobu na uniknięcie postrzału w stopę. Jeśli ktoś utworzy katalog B lub dowiązanie symboliczne do jakiegoś katalogu tuż przed uruchomieniem cp A Bpolecenia, nie zrobi tego, co zamierzałeś. A robienie [ -e B ] || [ -L B ] || cp A Bnadal ma warunki wyścigowe, których cp -Tn A Bnie ma.
Stéphane Chazelas,
6

-TMoże dostarczyć awarię jeśli katalog nieprawidłowo istnieje za to, co powinno być plik docelowy:

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

Oznacza to, że zamiast udanego nieoczekiwanego kopiowania do podkatalogu pojawia się ostrzeżenie i zły stan wyjścia, co może spowodować przerwanie skryptu, a człowiek sprawdza, dlaczego istnieje katalog, w którym nie powinien być jednością.

gałązka
źródło
0

Używanie flagi jest również znacznie bardziej przejrzyste i wiąże się z mniejszym ryzykiem niezamierzonych efektów, gdy polecenie jest używane w skrypcie zamiast ręcznie wprowadzone. Łata kropek na ścieżkach w skrypcie może skończyć się wszelkiego rodzaju nieoczekiwanymi psotami.

rackandboneman
źródło