Próbowałem wywołać komendę chmod w niewłaściwej kolejności. chmod file.txt -rZ jakiegoś powodu to zadziałało. chmod file.txt +rZ drugiej strony odmówił pracy. Dlaczego to? Z jakiego powodu jedno polecenie działa, a drugie nie?
Próbowałem wywołać komendę chmod w niewłaściwej kolejności. chmod file.txt -rZ jakiegoś powodu to zadziałało. chmod file.txt +rZ drugiej strony odmówił pracy. Dlaczego to? Z jakiego powodu jedno polecenie działa, a drugie nie?
Odpowiedzi:
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 chmodwymaga , 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 filepreferowane jest „ ” ichmod -w file(bez--) narzeka, jeśli zachowuje się inaczej niż to, cochmod a-w filezrobiłby „ ”.
W skrócie, przeanalizowane opcje getoptsą poprzedzone znakiem -. Podobnie jak w ls -a, ajest opcją. Długa forma ls --allma alljako opcję. rm -rf(odpowiednik rm -r -f) ma obie opcje ri fopcje.
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 chmodpierwszym 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 filelub chmod -- -w filezamiast 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.txtbyłoby najbardziej niezawodnym wywołaniem.chmod +r file.txt działa, ponieważ pierwszy argument jest interpretowany pozycyjnie jako tryb.chmod -r file.txtnadal działa, ponieważ -rjest interpretowany jako krótka ropcja i ma specjalną obudowę.chmod -- -r file.txtjest poprawny i działa, ponieważ -rjest interpretowany pozycyjnie jako tryb. Różni się to od przypadku bez --ponieważ z nie jest interpretowane jako opcja .---rchmod file.txt -rnadal działa, ponieważ -rjest interpretowany jako krótka ropcja i ma specjalną obudowę. Opcje nie są zależne od pozycji. To technicznie narusza nieudokumentowane dziwactwo.chmod file.txt +rnie działa, ponieważ +rjest operandem, a nie opcją. Pierwszy operand ( file.txt) jest interpretowany jako tryb ... i nie może zostać przeanalizowany.getopt Polecenie , a nie procedura biblioteczna w sekcji 3 . Po drugie, odnosi się to do optstring, tj. Listy akceptowanych opcji (w chmodźródle optstringjest 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ów argv zawierającą argumenty przekazane do programu.
a+rwxi robisz coś takiegochmod * +r, aa+rwxplik jest na pierwszym miejscu w rozszerzeniu globalnym.