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 jakorm -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='@(.|..)'
).
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)