Mam katalog zawierający 10144911 plików. Do tej pory próbowałem:
for f in ls; do sed -i -e 's/blah/blee/g' $f; done
Rozbiłam moją skorupę, ls
jest w tyldie, ale nie wiem, jak ją stworzyć.
ls | xargs -0 sed -i -e 's/blah/blee/g'
Za dużo argumentów sed
find . -name "*.txt" -exec sed -i -e 's/blah/blee/g' {} \;
Nie można rozwidlić więcej pamięci
Wszelkie inne pomysły na tworzenie tego rodzaju polecenia? Pliki nie muszą się ze sobą komunikować. ls | wc -l
wydaje się działać (bardzo powoli), więc musi być możliwe.
sed
dla każdego pliku. Nie jestem pewien, czy istnieje sposób na otwarcie, edycję, zapisanie i zamknięcie serii plikówsed
; jeśli prędkość jest niezbędna, możesz użyć innego programu, na przykład Perla lub Pythona.sed
jest prawdopodobnie szybszy niż uruchomieniepython
lubperl
też, chyba że zrobisz wszystko w tym tłumaczu.Odpowiedzi:
Wypróbuj to:
Poda tylko jedną nazwę pliku do każdego wywołania
sed
. To rozwiąże problem „zbyt wielu argumentów dla sed”. Ta-P
opcja powinna umożliwiać rozwidlenie wielu procesów jednocześnie. Jeśli 0 nie działa (powinno działać jak najwięcej), wypróbuj inne liczby (10? 100? Liczba rdzeni, którą masz?), Aby ograniczyć liczbę.źródło
find . -name \*.txt -print0
uniknąć sytuacji, w której powłoka rozszerzy glob i spróbuje przydzielić miejsce na 10 milionów argumentów do znalezienia .Przetestowałem tę metodę (i wszystkie pozostałe) na 10 milionach (pustych) plikach o nazwie „hello 00000001” na „hello 10000000” (14 bajtów na nazwę).
UPDATE: Mam teraz obejmował quad-core bieg na
'find |xargs'
metodzie (nadal bez 'sed'; tylko echo> / dev / null) ..Oto podsumowanie tego, jak poszły podane odpowiedzi, gdy uruchomiono je z danymi testowymi wymienionymi powyżej. Te wyniki obejmują tylko podstawowe koszty ogólne; tzn. „sed” nie został nazwany. Proces sed prawie na pewno będzie najbardziej czasochłonny, ale pomyślałem, że byłoby interesujące zobaczyć porównanie nagich metod.
'find |xargs'
Metoda Dennisa , wykorzystująca pojedynczy rdzeń, zajęła * 4 godziny 21 minut ** dłużej niżbash array
metoda wno sed
biegu ... Jednak wielordzeniowa przewaga oferowana przez „find” powinna przewyższać różnice czasowe pokazane, gdy wezwany jest sed przetwarzanie plików ...źródło
Kolejna szansa na całkowicie bezpieczne znalezienie :
źródło
Jest to głównie nie na temat, ale możesz użyć
Główną korzyścią (ponad
... xargs ... -I {} ... sed ...
) tutaj jest szybkość: unikasz wywoływaniased
10 milionów razy. Byłoby jeszcze szybciej, gdybyś mógł uniknąć używania Pythona (ponieważ Python jest stosunkowo powolny), więc perl może być lepszym wyborem dla tego zadania. Nie jestem pewien, jak zrobić odpowiednik w perlu.Działa to w ten sposób, że
xargs
wywołuje Python z tyloma argumentami, ile może zmieścić się w jednym wierszu poleceń i kontynuuje działanie, dopóki nie zabraknie argumentów (które są dostarczane przezls -f *.txt
). Liczba argumentów dla każdego wywołania będzie zależeć od długości nazw plików i, hmm, innych rzeczy.fileinput.input
Funkcja daje kolejne linie z plików nazwanych w każdym wywołaniu argumentów za, ainplace
opcja mówi, że w magiczny sposób „złapać” wyjście i używać go zastąpić każdą linię.Zauważ, że ciąg Pythona
replace
metoda nie używa wyrażeń regularnych; jeśli ich potrzebujesz, musiszimport re
i użyjprint re.sub(line, "blah", "blee")
. Są to RegExps kompatybilne z Perl, które są swego rodzaju mocno ufortyfikowanymi wersjami tych, które otrzymujeszsed -r
.edytować
Jak wspomina akira w komentarzach, oryginalna wersja używa glob (
ls -f *.txt
) zamiastfind
polecenia nie działałaby, ponieważ globs są przetwarzane przezbash
samą powłokę ( ). Oznacza to, że zanim polecenie zostanie uruchomione, w wierszu polecenia zostanie wstawionych 10 milionów nazw plików. Jest prawie pewne, że przekracza maksymalny rozmiar listy argumentów polecenia. Możesz użyćxargs --show-limits
do tego informacji specyficznych dla systemu.Uwzględniany jest również maksymalny rozmiar listy argumentów
xargs
, co ogranicza liczbę argumentów przekazywanych do każdego wywołania Pythona zgodnie z tym limitem. Ponieważxargs
nadal będziesz musiał wywoływać Pythona kilka razy, sugestia Akiry, aby użyćos.path.walk
listy plików, prawdopodobnie zaoszczędzi ci trochę czasu.źródło
os.path.walk()
?.
i..
. Z pewnością istnieją inne sposoby, aby to zrobić (tj.find
), Ale staram się jak najściślej trzymać się tego, co rozumie OP. Jest to również powód nieużywaniaos.path.walk
.os.path.walk
całkiem łatwo.Próbować:
źródło
ls -f
byłoby lepiej; czy naprawdę chcesz na to poczekaćstat()
i posortować tyle plików?