Depuis /unix//a/458074/674
N'oubliez pas d'utiliser
--
lors du passage d'arguments arbitraires aux commandes (ou utilisez des redirections si possible). Alorssort -- "$f1"
ou mieuxsort < "$f1"
au lieu desort "$f1"
.
Pourquoi est-il préférable d'utiliser --
et de rediriger?
Pourquoi est sort < "$f1"
préféré à sort -- "$f1"
?
Pourquoi est sort -- "$f1"
préféré à sort "$f1"
?
Merci.
Réponses:
échoue pour les valeurs
$f1
commençant par-
ou ici pour le cas desort
certaines commençant par+
(peut avoir de graves conséquences pour un fichier appelé-o/etc/passwd
par exemple).(où
--
signale la fin des options) résout la plupart de ces problèmes mais échoue toujours pour le fichier appelé-
(quisort
interprète comme signifiant son stdin à la place).N'a pas ces problèmes.
Ici, c'est le shell qui ouvre le fichier. Cela signifie également que si le fichier ne peut pas être ouvert, vous obtiendrez également un message d'erreur potentiellement plus utile (par exemple, la plupart des shells indiqueront le numéro de ligne dans le script), et le message d'erreur sera cohérent si vous utilisez des redirections autant que possible pour ouvrir des fichiers.
Et en
(contrairement à
sort -- "$f1" > out
), s'il"$f1"
ne peut pas être ouvert,out
ne sera pas créé / tronqué etsort
ne sera même pas exécuté.Pour effacer une certaine confusion possible (après les commentaires ci-dessous), cela n'empêche pas la commande d'
mmap()
ingérer le fichier ou d' y pénétrerlseek()
(cesort
n'est pas le cas non plus) à condition que le fichier lui-même soit recherché. La seule différence est que le fichier est ouvert plus tôt et sur le descripteur de fichier 0 par le shell par opposition à plus tard par la commande éventuellement sur un descripteur de fichier différent. La commande peut toujours rechercher / mmap qui fd 0 à sa guise. Cela ne doit pas être confondu aveccat file | cmd
oùcmd
le stdin de cette fois est un tuyau qui ne peut pas être mappé / recherché.la source
sort
à lire les données séquentiellement et vous ne pouvez pasmmap
le fichier. Bien que celasort
puisse ne pas avoir beaucoup de problèmes, considérez les performances deless <file
etless file
. Dans le premier cas, illess
doit conserver tout le contenu du fichier dans la mémoire, dans le second cas, il est autorisé à lire uniquement les parties qu'il souhaite. Imaginez maintenant qu'ilfile
s'agit d'un fichier journal de 100 Go ...less <file
garde tout le fichier en mémoire, mais ce n'est pas forcé, c'est un défaut de moins. Seulcat file | less
est obligé de le faire. Vérifiezless /dev/fd/0 <f
, qui ne conserve pas le fichier en mémoire, même s'il le reçoit sur stdin. C'est une idée fausse très répandue que stdin sous Unix est imprenable. En fait, il peut être recherché, selon le type de fichier.read()
lire les données séquentiellement à partir d'un fichier, tout enmmap()
lisant le fichier entier en mémoire à la fois?sort
par POSIX. Mais c'est vrai que ce n'est pas toujours supporté.getopt()
fonction C reconnaît cette signification de l'argument--
. Mais le point principal est celui que vous acceptez: la gestion des arguments est le domaine des programmes individuels, et tous ne les traitent pas--
spécialement.Le problème est le nom des fichiers commençant par un tiret.
sort "$f1"
ne fonctionne pas si la valeur def1
commence par-
car la commande interprétera la valeur comme une option. Cela entraîne généralement une erreur, mais cela peut même entraîner une faille de sécurité . Avecsort -- "$f1"
, l'argument double tiret--
signifie «aucune option au-delà de ce point», donc la valeur def1
ne sera pas interprétée comme une option. Mais il y a encore un cas de bord: si la valeur def1
est un tiret et rien d'autre, alors ce n'est pas une option, c'est l'argument-
, qui signifie «entrée standard» (car l'argument est un fichier d'entrée; pour un fichier de sortie cela signifierait «sortie standard»).L'utilisation de la redirection évite tous ces pièges.
Cela s'applique à la plupart des commandes, pas seulement
sort
.la source
sort < "$f1"
cela fonctionnerait si la valeur était égale à-
? Ce n'est dans aucun shell que j'ai essayé.seq 10 > -; sort -
avecseq 10 > -; sort < -
.