Comment «réduire» un fichier nommé «-»?

17

J'ai accidentellement créé un fichier avec le nom -(par exemple, seq 10 > -). Ensuite, j'ai essayé de l'utiliser lesspour le voir, mais il se bloque simplement.

Je comprends que cela se produit car less -attend des entrées de stdin, donc il n'interprète pas le -comme un nom de fichier. J'ai essayé less \-mais ça ne marche pas non plus.

Alors, existe-t-il un moyen d'indiquer lessqu'il -s'agit d'un fichier et non de stdin?

Le mieux que j'ai pu obtenir est:

find -name '-' -exec less {} +
fedorqui
la source
2
@muru merci pour le commentaire, mais le doublon possible est si spécifique que je ne pense pas qu'il soit qualifié de "doublon exact". S'il a été reformulé en quelque chose de plus générique comme "comment accéder à un fichier commençant par '-'", peut-être.
fedorqui
4
Ce n'est pas une question en double. Le cas pour -seul est différent. -n'est pas une option.
Stéphane Chazelas
1
@terdon Je ne pense pas qu'avoir la même réponse signifie directement que ce sont des doublons. Il y avait un exemple quelque part dans Meta SO: si une question obtient une réponse avec "Non", est-ce que tout ce dont la bonne réponse est "Non" serait un doublon? Comme je l'ai déjà dit, il serait intéressant de reformuler le candidat de doublon pour qu'il soit plus générique; sinon, cela n'a pas beaucoup de sens de lui envoyer d'autres questions comme celle-ci.
fedorqui
4
@terdon, non. La solution acceptée là-bas ne fonctionnera pas ici. Et non, -n'est pas traité comme une option, c'est un problème totalement différent du cas des arguments qui se présentent comme des options.
Stéphane Chazelas
2
Il n'est pas nécessaire de mettre -entre guillemets simples comme '-'ou de lui échapper comme \-parce qu'il -n'est pas un caractère spécial pour les shells courants (au moins ceux compatibles POSIX). Le résultat est le même.
pabouk

Réponses:

53

Il suffit de le préfixer avec ./:

less ./-

Ou utilisez la redirection:

less < -

Notez que puisque -(par opposition à -xou --foo--par exemple) est considéré comme un nom de fichier spécial plutôt qu'une option, ce qui suit ne fonctionne pas:

less -- -   # THIS DOES NOT WORK
Howard
la source
3
BTW, c'est ce qui find -name '-' -exec less {} +fonctionne.
Stéphane Chazelas
6
@fedorqui, non c'est juste ça -et ./-(ou /path/to/-ou ../to/-) sont deux (4) chemins valides pour ce -fichier, mais un -argument est spécial pour less(signifie lu depuis stdin) tandis que ./-n'est pas spécial.
Stéphane Chazelas
2
@fedorqui find -name '-' -exec less {} +est le formulaire non standard pour find . -name '-' -exec less {} +. Il descend l'arborescence à .et trouve les fichiers et passe les chemins de ces fichiers comme arguments à less. Remplacez -exec lesspar -exec echo lesspour voir ce qui est exécuté.
Stéphane Chazelas
4
@haylem, --c'est pour marquer la fin des options. Cela n'aidera pas ici. Ce -n'est pas une option, c'est un argument spécial sans option. Voir aussi unix.stackexchange.com/a/56370 , unix.stackexchange.com/a/110756
Stéphane Chazelas
3
@haylem, essayez par vous-même. --est géré par getopt () pour marquer la fin des options, -n'est pas reconnu comme une option par getopt (), ce qui -sera reconnu comme un argument normal, qu'il --soit fourni ou non. Et comme argument normal, lesscomme la plupart des utilitaires de texte le traiteront comme signifiant stdin, ce que nous ne voulons pas ici.
Stéphane Chazelas
3

Remarque: ma réponse n'est PAS valide dans le cas de l'OP, et ne s'applique qu'aux outils suivant la convention mentionnée ci-dessous et pas dans le cas d'un fichier nommé exactement juste -(tiret), qui est souvent aussi un cas spécial pour spécifier cette lecture à partir de la norme entrée est attendue. Voir la réponse acceptée.

Laissant ceci ici car il contient des informations utiles pour d'autres cas sur lesquels on peut tomber lors de la recherche de réponses.


Doublez-le!

Utilisez la --convention standard double-dash ( ) pour indiquer le dernier argument:

less -- -FILENAME

Exemple

$ echo "meh" > -badname
$ less -badname
Number is required after -b
$ less -- -badname # GREAT SUCCESS!

Quoi?

Cet --argument découle d'une convention prise en charge par la plupart des implémentations des utilitaires de shell et des outils de ligne de commande, et la plupart des shells préconisent visiblement de la suivre lors de l'implémentation des outils CLI.

Recommandé par l'Open Group

L'OpenGroup le mentionne également dans la section Default description defaults (v6) de sa spécification de base:

Comportement par défaut: [...] Les utilitaires standard qui n'acceptent pas les options, mais qui acceptent les opérandes, reconnaîtront "-" comme premier argument à ignorer.

La nécessité de reconnaître "-" est due au fait que les applications conformes ont besoin d'un moyen de protéger leurs opérandes de toutes les options arbitraires que l'implémentation peut fournir en tant qu'extension. Par exemple, si l'utilitaire standard foo est répertorié comme ne prenant aucune option et que l'application devait lui donner un chemin d'accès avec un trait d'union, il pourrait le faire en toute sécurité comme suit:

foo -- -myfile

et éviter tout problème avec -m utilisé comme extension.

Et dans les directives de syntaxe utilitaire (v7):

Directive 10: Le premier argument qui n'est pas un argument d'option doit être accepté comme un délimiteur indiquant la fin des options. Tous les arguments suivants doivent être traités comme des opérandes, même s'ils commencent par le caractère «-».

Recommandé par Bash

Ici, extrait du manuel bash, à propos de ses fonctions internes le supportant:

Sauf indication contraire, chaque commande intégrée documentée dans cette section comme acceptant des options précédée de - accepte - pour signifier la fin des options.

Les fonctions intégrées:, true, false et test n'acceptent pas les options et ne traitent pas - spécialement. Les commandes internes exit, logout, break, continue, let et shift acceptent et traitent les arguments commençant par - sans exiger -. D'autres commandes internes qui acceptent des arguments mais qui ne sont pas spécifiées comme acceptant des options interprètent des arguments commençant par - comme des options non valides et nécessitent - pour empêcher cette interprétation.

Notez que l'écho n'interprète pas - pour signifier la fin des options.

Lecture supplémentaire

haylem
la source
2
+1: Solution la plus portable et indépendante des commandes, facile à retenir et considérée comme la "meilleure pratique"
mveroone
2
@Kwaio une référence sur la "meilleure pratique"? Sentez-vous simplement curieux à ce sujet.
fedorqui
24
Cette réponse s'applique aux arguments qui ressemblent à des options. Ce n'est pas le cas pour -lequel ce n'est pas une option. L'utilisation ./-ou la redirection lorsque cela est possible est généralement une meilleure approche car elle évite d'autres types de problèmes comme le foo=barof awkou that -. Voir aussi unix.stackexchange.com/a/56370 , unix.stackexchange.com/a/110756
Stéphane Chazelas
7
Comme le dit Stéphane, cela ne répond pas à la question. less -- -essaiera toujours de lire depuis stdin.
Michał Politowski
5
Vous voudrez peut-être supprimer la réponse (ou la déplacer vers l'autre question car il y a des références utiles ici) ou indiquer clairement qu'elle ne s'applique pas à ce cas particulier (et peut-être expliquer pourquoi ce qui serait encore plus utile).
Stéphane Chazelas