Używam następującego polecenia:
\cp -uf /home/ftpuser1/public_html/ftparea/*.jpg /home/ftpuser2/public_html/ftparea/
I pojawia się błąd:
-bash: /bin/cp: Argument list too long
Próbowałem też:
ls /home/ftpuser1/public_html/ftparea/*.jpg | xargs -I {} cp -uf {} /home/ftpuser2/public_html/ftparea/
Nadal dostałem -bash: / bin / ls: Lista argumentów za długa
Jakieś pomysły?
linux
bash
unix-shell
icelizard
źródło
źródło
ls
nie jest przeznaczony do tego rodzaju czynności. Zastosowaniefind
.ls
jest specjalnie zaprojektowany do tego: mywiki.wooledge.org/ParsingLsOdpowiedzi:
* .jpg rozwija się do listy dłużej niż jest w stanie obsłużyć powłokę. Spróbuj tego zamiast tego
źródło
Istnieje maksymalny limit długości listy argumentów dla komend systemowych - limit ten jest specyficzny dla dystrybucji na podstawie wartości
MAX_ARG_PAGES
czasu kompilacji jądra i nie można go zmienić bez ponownej kompilacji jądra.Ze względu na sposób, w jaki powłoka obsługuje globbing, wpłynie to na większość poleceń systemowych, gdy użyjesz tego samego argumentu („* .jpg”). Ponieważ glob jest najpierw przetwarzany przez powłokę, a następnie wysyłany do polecenia, polecenie:
jest zasadniczo taki sam jak powłoka, tak jakbyś napisał:
Jeśli masz do czynienia z wieloma plikami JPEG, może to bardzo szybko stać się niemożliwe do opanowania. W zależności od konwencji nazewnictwa i liczby faktycznie przetwarzanych plików, możesz uruchomić polecenie cp w innym podzbiorze katalogu na raz:
Może to działać, ale dokładna skuteczność zależy od tego, jak dobrze możesz podzielić listę plików na wygodne globalne bloki.
Globalny. Lubię to słowo.
Niektóre polecenia, takie jak find i xargs , mogą obsługiwać duże listy plików bez tworzenia list argumentów o boleśnie dużych rozmiarach.
Argument -exec uruchomi resztę wiersza poleceń jeden raz dla każdego znalezionego pliku przez find , zastępując {} każdą znalezioną nazwą pliku. Ponieważ polecenie cp jest uruchamiane tylko na jednym pliku na raz, limit listy argumentów nie stanowi problemu.
Może to być powolne ze względu na konieczność przetwarzania każdego pliku osobno. Korzystanie z xargs może zapewnić bardziej wydajne rozwiązanie:
xargs może pobrać pełną listę plików dostarczoną przez find i podzielić ją na listy argumentów o zarządzalnych rozmiarach i uruchomić cp na każdej z tych podlist.
Oczywiście istnieje również możliwość ponownej kompilacji jądra, ustawiając większą wartość dla
MAX_ARG_PAGES
. Jednak rekompilacja jądra to więcej pracy, niż zamierzam wyjaśnić w tej odpowiedzi.źródło
xargs
wydaje się być znacznie wydajniejszy, ponieważ wynikowa liczba wywołań poleceń jest znacznie mniejsza. W moim przypadku widzę 6-12-krotnie lepszą wydajność, gdy korzystamargs
wtedy, gdy zastosowanie-exec
rozwiązania z rosnącą liczbą plików zwiększa wydajność.Dzieje się tak, ponieważ
*.jpg
po rozwinięciu wyrażenie wieloznaczne ( ) przekracza limit długości argumentów wiersza poleceń (prawdopodobnie dlatego, że masz dużo plików .jpg/home/ftpuser/public_html/ftparea
).Istnieje kilka sposobów obejścia tego ograniczenia, na przykład używanie
find
lubxargs
. Zapoznaj się z tym artykułem, aby uzyskać więcej informacji na ten temat.źródło
Jak skomentował GoldPseudo, istnieje ograniczenie liczby argumentów, które można przekazać procesowi, który spawnujesz. Zobacz jego odpowiedź na dobry opis tego parametru.
Możesz uniknąć problemu, albo nie przekazując procesowi zbyt wielu argumentów, albo zmniejszając liczbę przekazywanych argumentów.
Pętla for w powłoce, find i ls, grep i pętla while robią to samo w tej sytuacji -
i
i
wszystkie mają jeden program, który odczytuje katalog (sama powłoka, find i ls) i inny program, który faktycznie pobiera jeden argument na wykonanie i iteruje całą listę poleceń.
Teraz będzie to powolne, ponieważ rm musi być rozwidlony i wykonany dla każdego pliku, który pasuje do wzorca * .jpg.
W tym momencie pojawia się xargs. xargs pobiera standardowe dane wejściowe i dla każdego N (dla Freebsd domyślnie jest to 5000), spawnuje jeden program z N argumentami. xargs jest optymalizacją powyższych pętli, ponieważ wystarczy rozwidlić programy 1 / N, aby przejść do całego zestawu plików, które odczytują argumenty z wiersza poleceń.
źródło
Istnieje maksymalna liczba argumentów, które można podać programowi, bash rozwija * .jpg do wielu argumentów do cp. Możesz to rozwiązać za pomocą find, xargs lub rsync itp.
Zobacz tutaj xargs i znajdź
/programming/143171/how-can-i-use-xargs-to-copy-files-that-have-spaces-and-quotes-in-their-names
źródło
Glob „*” rozszerza się do zbyt wielu nazw plików. Zamiast tego użyj find / home / ftpuser / public_html -name '* .jpg'.
źródło
Korzystanie z
+
opcjifind -exec
to znacznie przyspieszy operację.+
Opcja wymaga{}
, aby być ostatni argument tak użyciem-t /your/destination
(lub--target-directory=/your/destination
) opcjęcp
sprawia, że pracują.Od
man find
:Edycja : zmieniono argumenty na cp
źródło
cp
aby naprawić ten błąd.Wygląda na to, że masz zbyt wiele
*.jpg
plików w tym katalogu, aby umieścić je wszystkie w wierszu polecenia jednocześnie. Możesz spróbować:Konieczne może być sprawdzenie
man xargs
implementacji, aby sprawdzić, czy-I
przełącznik jest odpowiedni dla twojego systemu.Czy naprawdę chcesz skopiować te pliki do tej samej lokalizacji, w której już się znajdują?
źródło
ls
będzie miał ten sam problem! Zmieniłem się nafind
co nie.Idź do folderu
i wykonaj następujące czynności:
W ten sposób, jeśli folder „ftparea” ma podfoldery, może to mieć negatywny efekt, jeśli chcesz z niego tylko pliki „* .jpg”, ale jeśli nie ma żadnych podfolderów, to podejście będzie zdecydowanie szybsze niż za pomocą find i xargs
źródło