Dlaczego program unix mv nie potrzebuje opcji -R (rekurencyjnej) dla katalogów, ale cp tego potrzebuje?

58

Zawsze się mylę, kiedy trzeba użyć cplub mv: „czy potrzebuję -Ropcji podczas pracy z reż?” W GNU coreutils cppotrzebuje -Ri mvnie potrzebuje .

Po prostu nie mogę znaleźć żadnego powodu, dla którego cppotrzebuję -Ropcji kopiowania katalogów, a mvnie. Myślę, że cppisanie katalogów bez -R(ale zachowując się rekurencyjnie tak, jak tam jest -Ri jak to mvrobi) nie spowodowałoby żadnych problemów oprócz zerwania czyichś nawyków korzystania z tego narzędzia.

Znasz jakieś wytłumaczenie? Czy to może mieć jakiś powód dawno temu?


Dodatkowe pytanie: dlaczego programiści cpCoreutils domyślnie nie tworzą rekursywnie kopii katalogów?

rslnx
źródło

Odpowiedzi:

45

Katalog jest (koncepcyjnie) specjalnym „plikiem”, który zawiera listę nazw oraz numery i-węzłów, na które wskazują te nazwy. Niektóre nazwy mogą być podkatalogami. Istnieje specjalny wpis ..wskazujący katalog macierzysty.

Oczywiste jest więc, że zmiana nazwy pliku jest łatwa: wystarczy zmienić nazwę we wpisie katalogu, nic więcej. Odnosi się to do tego, czy plik jest w rzeczywistości plikiem, czy jest „plikiem” służącym do przechowywania zawartości innego katalogu. Rzeczywiście, to samo renamewywołanie systemowe działa zarówno.

Kopiowanie jest jednak znacznie mniej trywialną operacją. Państwo mogłoby po prostu skopiować katalogu „plik”, ale wtedy masz dwa katalogi, w których pliki są takie same (byliby hardlinki). Jeśli posiadasz system, który pozwala na tworzenie twardych linków do katalogów, byłoby to możliwe, ale ponieważ żaden nowoczesny system nie pozwala na to, przynajmniej dla użytkownika innego niż root, musisz wykonać tę kopię dla każdego podkatalogu. Możesz poprosić cpo takie zachowanie za pomocą cp -lR: -ltwardego linku, -Rtej rekurencji.

Ale pozostawienie wszystkiego połączonego prawdopodobnie nie jest tym, czego chcesz. Zamiast tego chcesz cpskopiować każdy plik. To dość kosztowna operacja: każdy plik musi zostać wczytany do pamięci i zapisany z powrotem na dysk w drugiej lokalizacji. W rzeczywistości potrzeba kilku wywołań systemowych, aby otwierać, czytać, pisać i zamykać pliki, i należy to powtórzyć dla każdego pliku.

Tradycyjne systemy plików działają również w ten sposób na dysku. Nie ma innego sposobu na skopiowanie wiązki plików, niż przejrzenie każdego z nich osobno i skopiowanie go, a są to typy systemów plików, które były używane podczas projektowania podstawowych narzędzi wiersza poleceń.

derobert
źródło
czy mving z jednego systemu plików do tego samego „po prostu zmienia nazwę we wpisie katalogu”?
rslnx
5
Nie, cross-system plików jest taki sam jak kopiowanie + usuwanie (w rzeczy samej, renamesyscall nie powiedzie się w przypadku cross-systemu plików). Nie jestem pewien, czy historycznie mvnawet wspierał ruchy cross-fs.
derobert
9
Mogę powiedzieć, z bezpośredniego doświadczenia, a nie spekulacji, że klasyka mvnie obsługuje ruchów między urządzeniami. Kiedyś po prostu próbował a rename()i drukował komunikat o błędzie, jeśli się nie udał. Nadal pamiętam zszokowane uczucie, kiedy po raz pierwszy przypadkowo skorzystałem z nowej funkcji. Dlaczego ten mv trwa tak długo? Och, robi rekursywną kopię, której nie zamierzałem!
Alan Curry
5
@RuslanKhusnullin Opcje wiersza poleceń dla popularnych poleceń są bardzo trudne do zmiany, ze względu na ich użycie w skryptach powłoki. Ktoś może zależeć od bieżącego zachowania cp typu „odmów kopiowania”. Cross-fs prawdopodobnie został uznany za mniej podatny na zerwanie, ale jak widać, nadal zaskakiwał Alana.
derobert
1
@derobert, nie zadziałało (system plików mvdziałał tylko dla pojedynczych plików na BSD 4.2 na VAX).
vonbrand
21

Zacznę od zadania kolejnego pytania:

Jaka jest różnica między cpi cp -R?

Cóż, bez -Rflagi możliwe jest tylko kopiowanie plików, ponieważ jest dość niezwykłe, że ktoś chce nierekurencyjnie skopiować katalog: kopia nierekurencyjna po prostu dałaby drugą nazwę katalogu, wskazując bezpośrednio na ten sam katalog Struktura. Ponieważ ludzie rzadko tego chcą, a tak naprawdę istnieje osobny program, który to robi ( ln), nierekurencyjna kopia katalogów jest niedozwolona.

Jaka może być różnica między mvi mv -R?

mv a bpo prostu zmienia nazwę pojedynczego wpisu w katalogu, więc jeśli katalog jest mvedytowany, jego zawartość jest również automatycznie przenoszona. W tym sensie mvjuż zapewnia właściwość rekurencyjną, tj. „Zmianę nazwy” wszystkich pozycji w katalogu o zmienionej nazwie, np. Z a/1na b/1. mvŻe tego nie robi, to znaczy, która zmienia nazwę katalogu ado b, ale zachowuje a/1jak a/1, nie jest to, co ludzie rozumieją, gdy odnosić się do ruchomych coś: Podczas przesuwania szafy, zawartość szafy są przenoszone również. Ta inna operacja, przenoszenie katalogu bez jego zawartości, jest już dostępna, nazywa się mkdir.

Daniel Kullmann
źródło
2
Zgadza się, właśnie o tym myślałem cpi mvjako operacje, które są nazywane: „wykonaj kopię” i „przenieś”. Więc jeśli chcę zrobić kopię filiżanki kawy, spodziewałbym się kolejnej filiżanki kawy z tym samym nadzieniem (napój kawowy). Problem polega na tym, że narzędzia nie są przeznaczone dla „zwykłych ludzi”, ale dla nerdów, którzy są świadomi struktury dysku i systemu plików, a nie bytów wirtualnych, takich jak pliki i katalogi plików.
rslnx
1
Dobrze skonstruowana, uzasadniona odpowiedź.
Spedge
1
@RuslanKhusnullin Twoja analogia do kawy działa cpi dla mv- nie wymaga żadnego poziomu „nerwowości” do zrozumienia, tylko podstawowy zdrowy rozsądek. Prawdziwa kopia filiżanki kawy nie jest pustą filiżanką - musisz rekurencyjnie kopiować nie tylko filiżankę, ale całą jej zawartość (kawę). Kiedy jednak przenosisz filiżankę kawy, nie musisz przenosić zawartości osobno - zawartość przesuwa się wraz z pojemnikiem.
jw013
1
@ jw013 Zaimponowałeś mi: „kiedy przenosisz filiżankę kawy, nie musisz przenosić zawartości osobno”, to naprawdę ma sens, dziękuję. Ale to kolejna warstwa abstrakcji. Myślę, że masz na myśli „traktuj plik jako i-węzeł”, podczas gdy myślę o plikach takich jak sekwencje bajtów bez meta-informacji.
rslnx
6

Zwykle, gdy mam problemy z logiką Uniksa, patrzę na Plan9, aby zobaczyć, jak wynalazcy Unixa wykonali te same zadania wiele lat później, nie ograniczając się do kompatybilności wstecznej.

Zatem Plan9 oferuje narzędzia cpi mvnarzędzia do pracy tylko z plikami.

`cp f1 f2` creates f2 and copies f1's contents into it.
`mv f1 f2` renames f1 to f2 if f1 and f2 are in the same dir
           does `cp f1 f2 && rm f1` else
           can rename dirs (`mv d1 d2`) but will not move dir to another dir.

Do skopiowania katalogu dircpjest naprawdę @{cd fromdir && tar c .} | @{cd todir && tar xT}(składnia powłoki rc)

Myślę, że jeśli chodzi o przeniesienie reż dircp d1 d2 && rm -r d1

Myślę, że decyzja o ograniczeniu cpi tylko mvdla operacji na plikach (nie na katalogach) zapewnia większą przejrzystość operacji na dyskach, a używanie tardo kopiowania drzew plików jest bardzo wygodne dla zrozumienia i pisania skryptów.

rslnx
źródło