Mój problem (w skrypcie z #!/bin/sh
) wygląda następująco: Próbuję zsumować wszystkie pliki w katalogu do celów archiwalnych. Plik sumy kontrolnej (w moim przypadku sha1) ze wszystkimi nazwami plików powinien znajdować się w tym samym katalogu. Powiedzmy, że mamy katalog ~/test
z plikami f1
i f2
:.
mkdir ~/test
cd ~/test
echo "hello" > f1
echo "world" > f2
Teraz obliczamy sumy kontrolne za pomocą
find -maxdepth 1 -type f -printf '%P\n' | xargs shasum
robi dokładnie to, co chcę, wyświetla listę wszystkich plików bieżącego katalogu i oblicza sumy sha1 (maxdepth można zmienić później). Dane wyjściowe STDOUT to:
f572d396fae9206628714fb2ce00f72e94f2258f f1
9591818c07e900db7e1e0bc4b884c945e6a61b24 f2
Niestety przy próbie zapisania tego pliku do pliku
find -maxdepth 1 -type f -printf '%P\n' | xargs shasum > sums.sha1
plik wynikowy wyświetla sumę kontrolną dla siebie:
da39a3ee5e6b4b0d3255bfef95601890afd80709 sums.sha1
f572d396fae9206628714fb2ce00f72e94f2258f f1
9591818c07e900db7e1e0bc4b884c945e6a61b24 f2
i dlatego nie powiedzie się później shasum --check
, z powodu oczywistego problemu dodatkowej modyfikacji pliku podczas zapisywania ostatniej sumy.
Rozejrzałem się i używając -p
flagi dla xargs
, dowiedziałem się, że jakoś tworzy plik wyjściowy przed wykonaniem polecenia find, dlatego dodatkowy plik zostanie znaleziony i zostanie sprawdzony ...
Wiem, że jako obejście problemu mogłem zapisać sumę kontrolną w innej lokalizacji (katalog tymczasowy przez mktemp
) lub wykluczyć ją w znalezieniu, ale chciałbym zrozumieć, dlaczego zachowuje się tak, jak to działa - co w moich oczach nie jest takie przydatne, na przykład, jeśli pierwsze polecenie sprawdzi, czy plik wyjściowy jest już na dysku, nigdy nie uzyska poprawnej odpowiedzi ...
sh
konieczne jest kilka inwokacji. Zauważ, że potrzebujesz argumentu $0
wcześniej {}
.
tee
zniknęła? Próbowałem i działa dobrze, tłumiłem również STDOUT dodając 1>/dev/null
. Czy było coś nie tak z odpowiedzią, czy błąd?
xargs
, to sama powłoka tworzy ten plik, ponieważ przed wykonaniem jakiegokolwiek polecenia najpierw przekierowuje wszystkie dane wejściowe, wyjściowe i potoki, tak że pofind
uruchomieniu plik wyjściowy już istnieje.-exec
Zamiast tego użyj :find -maxdepth 1 -type f -exec sh -c 'shasum "$@" > sums.sha1' {} +