Kiedy używam
cp -R inputFolder outputFolder
wynik zależy od kontekstu :
- jeśli
outputFolder
nie istnieje, zostanie utworzony, a ścieżka sklonowanego folderu będzieoutputFolder
. - jeśli
outputFolder
istnieje, utworzony zostanie klonoutputFolder/inputFolder
To okropne , ponieważ chcę utworzyć skrypt instalacyjny, a jeśli użytkownik uruchomi go dwa razy przez pomyłkę, utworzy go outputFolder
za pierwszym razem, a następnie przy drugim uruchomieniu wszystkie elementy zostaną utworzone ponownie outputFolder/inputFolder
.
- Chcę zawsze pierwszego zachowania: utwórz klon obok oryginału (jako rodzeństwo).
- Chcę
cp
być przenośny (np. MINGW nie zostałrsync
wysłany) - Sprawdziłem,
cp -R --parents
ale to odtwarza ścieżkę w górę drzewa katalogów (więc klon nie będzie,outputFolder
alesome/path/outputFolder
) --remove-destination
lub--update
w przypadku, gdy 2 nic nie zmieni, nadal rzeczy są kopiowaneoutputFolder/inputFolder
Czy istnieje sposób, aby to zrobić bez uprzedniego sprawdzenia istnienia outputFolder
(jeśli folder nie istnieje, to ...) lub użycia rm -rf outputFolder
?
Jaki jest uzgodniony, przenośny sposób UNIX?
mv
przenoszeniu kolekcji plików do jednego zwykłego pliku?rsync
?cp
, przesyłanie potokowe między dwomatar
poleceniami to niezawodny niezawodny sposób na kopiowanie drzew.rsync
wysłany.tar -C input -cf - . | tar -C output -xf -
działa.-C
zmienia katalog roboczy, ale nie jest to standardowa opcja, więc jeśli nie jest obsługiwany, musisz uruchomić dwie tabele w odpowiednich katalogach roboczych na początek, np.( cd input && tar -cf - . ) | ( cd output && tar -xf - )
Jeśli jednak masz do czynienia z Windows, użyłbym tylko odpowiedzi roaima.Odpowiedzi:
Użyj tego zamiast:
Działa to dokładnie tak samo, jak, powiedzmy,
cp -R aaa/bbb ccc
działa: jeśliccc
nie istnieje, to jest tworzone jako kopiabbb
i jego zawartość; ale jeśliccc
już istnieje, toccc/bbb
jest tworzony jako kopiabbb
i jego zawartość.W prawie każdym przypadku
bbb
daje to niepożądane zachowanie, które zauważyłeś w swoim pytaniu. Jednak w tej konkretnej sytuacjibbb
jest po prostu.
takaaa/bbb
jest naprawdęaaa/.
, co z kolei jest tak naprawdęaaa
, ale pod inną nazwą. Mamy więc dwa scenariusze:ccc
nie istnieje:Polecenie
cp -R aaa/. ccc
oznacza „utwórzccc
i skopiuj zawartośćaaa/.
doccc/.
, tzn. Skopiujaaa
doccc
.ccc
istnieje:Polecenie
cp -R aaa/. ccc
oznacza „skopiuj zawartośćaaa/.
doccc/.
, tzn. Skopiujaaa
doccc
.źródło
inputFolder/.
zamiastinputFolder
i rzeczywiście działa dla mnie na Windows / Git Bash. (Nie działa to jednak tylko z końcem/
, potrzebuję także kropki po ukośniku). Dałem +1, ponieważ jest interesujący, choć prawdopodobnie jest to zbyt trudne, aby użyć go w publicznym kodzie :)Nie kopiuj folderu, tylko kopiuj zawartość:
W ten sposób oboje upewnisz się, że katalog docelowy jest tworzony przy pierwszym uruchomieniu skryptu i unikniesz problemu podczas jego uruchamiania po raz drugi.
Chris Down bardzo poprawnie wskazuje, że w bashie pominie to pliki, których nazwa zaczyna się od
.
. Aby tego uniknąć, możesz uruchomićshopt -s dotglob
przed uruchomieniem powyższej komendy.Zarówno
-p
dla,mkdir
jak i-R
dlacp
są zdefiniowane przez POSIX, więc powinno to być całkowicie przenośne.źródło
.
. W bash możeszdotglob
do tego użyć .Wypróbuj
-T
opcjęcp
. Istnieje w GNU coreutilscp
wersja 8.22; poza tym może nie być przenośny.źródło
cp -T
(cp --no-target-directory
). unix.stackexchange.com/questions/94831/… Niestety moja wersjacp
jest znacznie starsza.-u
jest świetną opcją do dodania, aby był leniwy.Możesz także użyć
rsync
:(zwróć uwagę na ukośniki, szczególnie po pierwszym)
źródło
Moim zdaniem nie ma nic prostszego i bardziej przenośnego niż
rm -rf outputFolder
. Więc zawsze się z tym trzymam. Rozumiem, że twoje pytanie jest inne, ale uważam, że jest to najlepsza praktyka.źródło
cp
był taki sam, zarówno gdy katalog nie istnieje, jak i kiedy istnieje. O czym ty mówisz?cp
Komenda podana przez OP nie zachowuje uprawnienia (lub znaczniki czasu).Możesz użyć
-t
opcjicp
polecenia jako:teraz, jeśli folder docelowy nie istnieje, wygeneruje błąd:
Uwaga: powyższe polecenie skopiuje
inputFolder
wraz z zawartością (a nie tylko zawartą w nim zawartością)jeśli chcesz skopiować tylko jego zawartość
inputFolder
staje się nieco trudna (ponieważ musisz zachować ostrożność podczas korzystania z globowania powłoki przy użyciu gwiazdki *)teraz, jeśli folder docelowy nie istnieje, wygeneruje błąd:
pracuje z
cp (GNU coreutils) 8.23
źródło