Chmod i -r + r

13

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?

TestyTentacleLinux
źródło

Odpowiedzi:

18

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 „ ” i chmod -w file(bez --) narzeka, jeśli zachowuje się inaczej niż to, co chmod 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 .---r
  • chmod 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.
Kok
źródło
4
Może to mieć interesujące konsekwencje, jeśli na przykład masz plik o nazwie a+rwxi robisz coś takiego chmod * +r, a a+rwxplik jest na pierwszym miejscu w rozszerzeniu globalnym.
Jörg W Mittag
1
Lub plik o nazwie „-rf” w przypadku „rm *”.
Edheldil
@Edheldil Tak masz rację. To wydaje się być czymś, co powinno zostać
naprawione
Zauważ, że składnia OP nie jest POSIX man7.org/linux/man-pages/man1/getopt.1.html#SCANNING_MODES
Steven Penny
@StevenPenny To nie ma znaczenia. Po pierwsze, połączona strona podręcznika to sekcja 1, tzn. 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.
Bob