GNU/Linux >> Znalost Linux >  >> Linux

Smaže „rm .*“ někdy nadřazený adresář?

Výraz .* je rozšířen o bash, aby zahrnoval aktuální a nadřazený adresář:

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

Pokud spustím rm -rf .* na mém Debianu pomocí GNU bash, version 4.2.36(1)-release a rm z rm (GNU coreutils) 8.13 , dostávám tuto zprávu:

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

Je to věc GNU nebo je to POSIX? Existují nějaké *nix systémy, kde výše uvedený příkaz tiše odstraní . a .. ?

Je to také bezpečnostní funkce shellu nebo rm samotný příkaz?

Přijatá odpověď:

Nejnovější (od roku 2017) verze specifikace POSIX pro rm utility je zde (a předchozí tam) a zakazuje smazání . a .. .

Pokud je některý ze souborů tečka nebo tečka-tečka specifikován jako část základního názvu operandu (tj. konečná komponenta názvu cesty) nebo pokud se operand překládá do kořenového adresáře, rm zapíše diagnostickou zprávu se standardní chybou a neudělá nic. více s takovými operandy.

Jak poznamenal @jlliagre, část o / je doplněk v SUSv4.

Nejstarší veřejně dostupná specifikace Unixu, kterou jsem našel (XPF4 CAE rev2 (1994)), již specifikovala . a .. nelze odstranit, i když komentáře v protokolu změn GNU fileutils naznačují, že tomu tak již bylo ve starších specifikacích POSIX.

Všimněte si, že platí pro dir/.. a ../ také, ale některé implementace (včetně těch s certifikací UNIX, jako je Solaris 11 a macOS) stále neposkytují ochranu proti rm -rf ../ nebo rm -rf .*/ ).

historie

Počáteční unice

-r možnost rm byl přidán v Unixu V3 (1973), i když pouze odstraňoval obsah adresářů, stále budete muset použít rmdir k odstranění adresářů.

To se změnilo v Unixu V7 (1979, vydání, které také představilo Bourne shell a ze kterého pochází většina Unices). rm -r nyní odstranil i adresáře a neodstranil by .. adresářový strom. Manuová stránka uvádí:

Je zakázáno odstraňovat soubor .. pouze proto, abychom se vyhnuli antisociálním důsledkům neúmyslného provedení něčeho jako rm -r .* .

(ačkoli by se dalo namítnout, že rm -r .* je stále antisociální protože smaže vše, protože . je zahrnuta).

Stále souhlasil s odstraněním . i když by to neodpojilo . nebo .. záznamy. Pak tedy rm -r . byl efektivní způsob, jak vyprázdnit aktuální adresář.

Všimněte si také, že ochrana byla pouze pro doslovný .. argument, nikoli pro dir/.. nebo ./.. . Takže rm -rf ./.* by stále rekurzivně odstranil vše v nadřazeném adresáři.

Je zajímavé vidět, že to již bylo řešením chyby/chybné funkce, kterou by globy mohly obsahovat . a .. v jejich expanzi. To bylo opraveno ve Forsyth shellu (základ pro původní Minix shell a pdksh) na konci 80. let, zsh (1990) a fish (2005), ale ne jiné shelly a zejména ne POSIX sh jazyk, který vyžaduje rozšíření .* zahrnout . a .. pokud jsou vráceny readdir() (bash řeší problém částečně pouze pomocí shopt -s dotglob where globs (kromě .xxx jedničky) nezahrnují . nebo .. a pomocí ksh , můžete to opravit provedením FIGNORE='@(.|..)' ).

Související:Jak odstranit soubor, který je používán jiným procesem?

Kdy přesně zakazuje . stejně jako bylo přidáno, není vždy jasné a liší se s každým Unixem. Několik zjištění níže.

BSD

Zákaz . byla přidána někdy mezi 2.9BSD (1983) a 2.10BSD (1987) a mezi 4.2BSD (1983) a 4.3BSD (1986) (viz tato změna s časovým razítkem 1985 v unix-history-repo).

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'n");

Pro dir/. a dir/.. , viz tato změna v roce 1988 (BSD 4.3 Net/1).

K dnešnímu dni rm FreeBSD (a odvozeniny jako macOS) stále vyprázdní aktuální nebo nadřazený adresář po rm -rf ./ nebo rm -rf ../ ačkoli (záleží na rm -rf .*/ ).

Systém V

Nemám mnoho informací, protože zdroj ani binární kód nejsou veřejně dostupné pro deriváty AT&T Unix po V7. HPUX (založený na systému III) ve svém online manuálu stále uvádí, že zakazuje pouze .. zatímco účinně zakazuje obojí, což je známkou toho, že pravděpodobně alespoň SysIII nezakázal smazání . (upravit :Nyní se podíváme na SysIII rm zdrojový kód se od Unixu V7 prakticky nezměnil).

Všechny ostatní online příručky, které jsem zkontroloval, zmiňují smazání . nebo .. je zakázáno, což lze očekávat v souladu s POSIX.

Solaris rm stále vyprázdní aktuální nebo nadřazený adresář po rm -rf ./ nebo rm -rf ../ .

GNU

První changelog pro GNU fileutils obsahuje všechny historické informace.

Zatímco původně ani smazání . nebo .. byly zakázány, .. bylo zakázáno nejprve a poté obojí (včetně dir/. ), to vše v letech 1990 až 1991.

jiné

Jak jsme viděli, v zsh , rozšíření .* (nebo jakákoli globus) nikdy neobsahuje . nebo .. (dokonce i v sh emulační režim). rm vestavěný (který získáte, pokud zmodload zsh/files ) proto nezachází s . nebo .. speciálně. Takže s tím zsh vestavěný, můžete rm -rf . nebo rm -rf .. vyprázdnit . nebo .. , ale rm -rf .* neodstraní . nebo .. .

V busyboxu rm , zákaz smazání . a .. byl přidán v 0,52 (2001)


Linux
  1. Jak nainstalovat R 3.3.1 do vlastního adresáře?

  2. Rsync mění oprávnění k adresáři?

  3. Jak spočítat počet souborů v adresáři a odstranit nejstarší, pokud počet překročí 5?

  1. Smazat nadřazený adresář (neprázdný) Pokud je konkrétní podřízený adresář prázdný?

  2. 5 Praktické příklady odstranění / odstranění adresáře v Linuxu

  3. Odeberte symbolický odkaz na adresář

  1. Jak nastavím pracovní adresář nadřazeného procesu?

  2. Co znamená opt (jako v adresáři opt)? Je to zkratka?

  3. Jaký je nejrychlejší způsob odstranění všech souborů a podsložek v adresáři?