Mój przyjaciel wskazuje, że jeśli to zrobisz:
perl -pi.bak -e 's/foo/bar/' somefile
kiedy „somefile” jest w rzeczywistości dowiązaniem symbolicznym, perl robi to, co mówią doktorzy:
Robi to poprzez zmianę nazwy pliku wejściowego, otwarcie pliku wyjściowego pod oryginalną nazwą i wybranie tego pliku wyjściowego jako domyślnego dla instrukcji print (). Rozszerzenie, jeśli jest dostarczone, służy do modyfikacji nazwy starego pliku w celu utworzenia kopii zapasowej [...]
W rezultacie powstaje nowe dowiązanie symboliczne „somefile.bak” wskazujące na niezmieniony plik rzeczywisty oraz nowy, zmieniony zwykły plik „somefile” ze zmianami.
W wielu przypadkach podążanie za dowiązaniem symbolicznym byłoby pożądanym zachowaniem (nawet jeśli pozostawia ono niejednoznaczną prawidłową lokalizację pliku .bak). Czy istnieje prosty sposób, aby to zrobić inaczej niż testowanie dowiązań symbolicznych w opakowaniu i odpowiednia obsługa sprawy?
( sed
robi to samo, za co jest tego warte.)
-p -i
skryptu.Odpowiedzi:
Zastanawiam się, czy małe
sponge
narzędzie ogólnego zastosowania („wchłanianie standardowych danych wejściowych i zapisywanie do pliku”) z moreutils będzie pomocne w tym przypadku i czy będzie podążało za dowiązaniem symbolicznym.Autor opisuje
sponge
tak:źródło
sponge
takie zastosowanie w praktyce? Co do mnie: jeszcze nie. Czy mógłbyś zostawić komentarz stwierdzający, czy zachował się on w teście tak, jak chciałem tutaj? Och, widzę komentarz. Dziękuję za potwierdzenie!file
w powyższym przykładzie znajduje się dowiązanie symboliczne, łącze jest pozostawione w spokoju, a rzeczywisty plik ulega zmianie.Jeśli wiesz, że
somefile
jest to dowiązanie symboliczne, możesz jawnie podać pełną ścieżkę do pliku w następujący sposób:perl -pi.bak -e 's/foo/bar/' $(readlink somefile)
W ten sposób oryginalne dowiązanie symboliczne pozostaje nienaruszone, ponieważ zastępowanie odbywa się teraz bezpośrednio z oryginalnym plikiem.
źródło
readlink
może być nadal innym dowiązaniem symbolicznym. Najlepiej byłoby użycie-f
lub-e
gdzie dostępne lubzsh
„s$file:P
lub(:P)
glob kwalifikator jak pokazano @ikegami dostać dowiązaniem wolna drogę.Jeśli masz do czynienia z jednym plikiem, komenda wyglądałaby następująco:
Rozwiązanie jest następujące:
To obsługuje zarówno dowiązania symboliczne, jak i nie-dowiązania symboliczne.
Jeśli masz do czynienia z dowolnie dużą liczbą plików, polecenie wyglądałoby następująco:
Rozwiązanie jest następujące:
To obsługuje zarówno dowiązania symboliczne, jak i nie-dowiązania symboliczne.
Zastrzeżenie
readlink
nie jest standardowym poleceniem, więc jego obecność, argumenty i funkcjonalność różnią się w zależności od systemu, więc sprawdź swoją dokumentację. Na przykład niektóre implementacje mają-f
(których można również użyć tutaj), ale nie-e
niektóre, żadne z nich.busybox
„sreadlink -f
zachowuje się jak GNUreadlink -e
. Niektóre systemy mająrealpath
polecenie, zamiastreadlink
którego ogólnie zachowuje się jak GNUreadlink -f
.Uwaga: w GNU
readlink -e
dowiązania symboliczne, których nie można rozpoznać w istniejącym pliku, są po cichu usuwane.źródło
$var:P
nie działa dla mnie. (X='tmp' zsh -c 'perl -E"say for @ARGV" $X:P'
wynikitmp:P
)$var:P
. W starszych wersjach zawsze możesz użyć$var:A
zamiast tego. Zobacz instrukcję różnic i na stronie zsh.org/mla/users/2016/msg00593.html uzasadnienie wprowadzenia:P
(prawdziwyrealpath()
interfejs).:A
dodano w 4.3.10 (2009), GNUreadlink -z
w 2012 roku, nie znam żadnej innejreadlink
implementacji, która obsługuje-z
). Zauważ, że w GNUxargs
zazwyczaj potrzebujesz tej-r
opcji, chyba że możesz zagwarantować, że dane wejściowe nie będą puste. Tutaj nie jest to wielka sprawa (chyba żeperl
kod zawiera instrukcjęBEGIN
/END
), po prostu dostaniesz-i used with no filenames on the command line, reading from STDIN.
ostrzeżenie, jeśli tak się stanie.-r
dokumentację. Myślałem, że zrobiłem coś przeciwnego. Gotowy