Próbowałem wywołać komendę chmod w niewłaściwej kolejności. chmod file.txt -r
Z jakiegoś powodu to zadziałało. chmod file.txt +r
Z drugiej strony odmówił pracy. Dlaczego to? Z jakiego powodu jedno polecenie działa, a drugie nie?
To dziwne, jak GNU chmod obsługuje dane wejściowe i nie jest przenośny dla wszystkich implementacji chmod zgodnych z POSIX.
Zauważ, że składnia coomand-line POSIX chmod
wymaga , aby tryb był na pierwszym miejscu, podobnie jak GNUchmod
(opcje powinny również występować przed trybem). Wszystko inne jest nieudokumentowanym dziwactwem dotyczącym implementacji.
Teraz, dlaczego tak się dzieje w tej konkretnej implementacji:
Jest to wskazane w instrukcji :
Zazwyczaj jednak
chmod a-w file
preferowane jest „ ” ichmod -w file
(bez--
) narzeka, jeśli zachowuje się inaczej niż to, cochmod a-w file
zrobiłby „ ”.
W skrócie, przeanalizowane opcje getopt
są poprzedzone znakiem -
. Podobnie jak w ls -a
, a
jest opcją. Długa forma ls --all
ma all
jako opcję. rm -rf
(odpowiednik rm -r -f
) ma obie opcje r
i f
opcje.
Cała reszta to argument nie będący opcją, technicznie nazywane operandami . Lubię nazywać te argumenty pozycyjne , ponieważ ich znaczenie zależy od ich względnej pozycji. W chmod
pierwszym argumentem pozycyjnym jest tryb, a drugim argumentem pozycyjnym jest nazwa pliku.
Optymalnie tryb nie powinien prowadzić z -
. Jeśli tak, powinieneś użyć --
do wymuszenia parsowania jako argumentu zamiast opcji (np. Użyj chmod a-w file
lub chmod -- -w file
zamiast chmod -w file
. Jest to również sugerowane przez POSIX.
Jeśli spojrzysz na kod źródłowy , zauważysz, że używa on getopt do analizowania opcji wiersza poleceń. Tutaj jest specjalna obsługa trybów „niepoprawnych”, takich jak -w
:
case 'r':
case 'w':
case 'x':
case 'X':
case 's':
case 't':
case 'u':
case 'g':
case 'o':
case 'a':
case ',':
case '+':
case '=':
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/* Support nonportable uses like "chmod -w", but diagnose
surprises due to umask confusion. Even though "--", "--r",
etc., are valid modes, there is no "case '-'" here since
getopt_long reserves leading "--" for long options. */
Biorąc twój przykład:
chmod a-r file.txt
byłoby najbardziej niezawodnym wywołaniem.chmod +r file.txt
działa, ponieważ pierwszy argument jest interpretowany pozycyjnie jako tryb.chmod -r file.txt
nadal działa, ponieważ -r
jest interpretowany jako krótka r
opcja i ma specjalną obudowę.chmod -- -r file.txt
jest poprawny i działa, ponieważ -r
jest interpretowany pozycyjnie jako tryb. Różni się to od przypadku bez --
ponieważ z nie jest interpretowane jako opcja .--
-r
chmod file.txt -r
nadal działa, ponieważ -r
jest interpretowany jako krótka r
opcja i ma specjalną obudowę. Opcje nie są zależne od pozycji. To technicznie narusza nieudokumentowane dziwactwo.chmod file.txt +r
nie działa, ponieważ +r
jest operandem, a nie opcją. Pierwszy operand ( file.txt
) jest interpretowany jako tryb ... i nie może zostać przeanalizowany.
a+rwx
i robisz coś takiegochmod * +r
, aa+rwx
plik jest na pierwszym miejscu w rozszerzeniu globalnym.getopt
Polecenie , a nie procedura biblioteczna w sekcji 3 . Po drugie, odnosi się to dooptstring
, tj. Listy akceptowanych opcji (wchmod
źródleoptstring
jest ustawiona na"Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"
). Połączona sekcja „TRYBY SKANOWANIA” nie ma nic wspólnego z tablicą argumentówargv
zawierającą argumenty przekazane do programu.