web-dev-qa-db-fra.com

L'espace n'est-il pas autorisé dans un nom de fichier?

Il est dit que sous Unix et Linux en général, vous devez éviter d'avoir des espaces dans le nom de fichier d'un fichier (fichier ordinaire, dir, lien, fichier de périphérique, ...).

Mais je fais ça tout le temps. Pour un nom de fichier avec un espace à l'intérieur,

  • Dans Nautilus, le caractère espace est affiché comme un espace.
  • Dans le terminal Bash, j'utilise soit \ pour représenter un espace ou placer le nom de fichier dans une paire de guillemets doubles.
  • dans les fichiers de certaines applications (Nautilus, je ne sais pas si le système d'exploitation le fera également), le nom de fichier est écrit avec l'espace remplacé par %20.

Un espace n'est-il vraiment pas autorisé dans un nom de fichier?

Comment utilisez-vous ou gérez-vous correctement un espace dans un nom de fichier?

32
Tim

Espaces, et en effet tous les caractères sauf / et NUL, sont autorisés dans les noms de fichiers. La recommandation d'utiliser pas les espaces dans les noms de fichiers vient du risque qu'ils soient mal interprétés par un logiciel qui les prend mal en charge. On peut dire que ce logiciel est bogué. Mais on peut aussi soutenir que les langages de programmation tels que les scripts Shell facilitent trop facilement l'écriture de logiciels qui se cassent lorsqu'ils sont présentés avec des noms de fichiers contenant des espaces, et ces bogues ont tendance à se faufiler parce que les scripts Shell ne sont pas souvent testés par leurs développeurs utilisant des noms de fichiers avec des espaces dans leur.

Espaces remplacés par %20 n'est pas souvent vu dans les noms de fichiers. Ceci est principalement utilisé pour les URL (Web). Bien qu'il soit vrai que le codage% à partir d'URL se retrouve parfois dans les noms de fichiers, souvent par accident.

49
Celada

Les espaces sont autorisés dans les noms de fichiers, comme vous l'avez observé.

Si vous regardez l'entrée "la plupart des systèmes de fichiers UNIX" dans ce graphique dans wikipedia , vous remarquerez:

  • Tout jeu de caractères 8 bits est autorisé. Nous pouvons subsumer 7 bits ASCII sous ce parapluie aussi, car il s'agit d'un sous-ensemble de divers ensembles 8 bits et est toujours implémenté en utilisant des octets 8 bits.

  • Les seuls caractères interdits sont / et "null". "Null" fait référence à un octet zéro, mais ceux-ci ne sont de toute façon pas autorisés dans les données de texte.

Cependant , si vous utilisez le Shell, vous vous rendrez peut-être compte que certains caractères créeront des tracas, surtout *, qui est un opérateur de globalisation POSIX.

Selon la façon dont vous voulez définir les "tracas", vous pourrait inclure des espaces (espaces, tabulations, nouvelles lignes, etc.) là-dedans, car cela crée le besoin de citer avec "". Mais cela est inévitable, car les espaces sont autorisés, alors ...

Comment utilisez-vous ou gérez-vous correctement un espace dans un nom de fichier?

Dans un contexte Shell/ligne de commande, encapsulez le nom de fichier entre guillemets simples ou doubles (mais notez ce ne sont pas les mêmes WRT autres problèmes), ou échappez les espaces avec \, par exemple.:

> foo my\ file\ with\ spaces\ in\ the\ name
17
goldilocks

La raison est en grande partie historique - WAY retour dans la brume des espaces de temps n'était pas autorisé dans les noms de fichiers, donc les espaces ont été utilisés comme séparateurs de mot-clé/nom de fichier. Les futurs interprètes Shell devaient être rétrocompatibles avec les anciens scripts, et nous sommes donc coincés avec le mal de tête que nous avons aujourd'hui.

Les développeurs de processus qui n'ont pas besoin de beaucoup traiter avec les humains peuvent rendre les choses beaucoup plus faciles en supprimant complètement les espaces. Apple fait cela, le contenu de/System/Library/CoreServices/contient très peu d'espaces, les programmes avec des espaces sont ouverts au nom de l'utilisateur et WouldLookStrangeIfCamelCased. Des chemins Unix similaires évitent également les espaces .

(anecdote quelque peu apparentée: au milieu des années 90, un drone Windows a dit "Nommez une chose que vous pouvez faire sur un Mac que je ne peux pas faire sous Windows" -> "Utilisez 12 caractères dans un nom de fichier." -> Silence. Les espaces étaient également possible dans ces 12 caractères)

3
paul

Alors oui, comme cela est dit à plusieurs reprises ailleurs, un nom de fichier peut contenir presque n'importe quel caractère. Mais il faut dire qu'un nom de fichier est pas un fichier. Il a un certain poids en tant que fichier attribut en ce que vous avez généralement besoin d'un nom de fichier pour ouvrir un fichier, mais un nom du fichier uniquement points vers le fichier réel. C'est un lien, stocké dans le répertoire qui l'a enregistré, à côté de numéro d'inode - qui est une approximation beaucoup plus proche d'un fichier réel.

Alors, vous savez, appelez ça comme vous voulez. Le noyau s'en fiche - toutes les références de fichiers qu'il gérera traiteront de toute façon les vrais numéros d'inode. Le nom de fichier est une chose pour la consommation humaine - si vous voulez en faire une chose folle, eh bien, c'est votre système de fichiers. Ici, je vais faire des trucs fous:

Je vais d'abord créer 20 fichiers et les nommer avec uniquement des espaces, chaque nom de fichier contenant un espace de plus que le dernier:

until [ $((i=$i+1)) -gt 20 ]
do  v=$v' ' && touch ./"$v"
done

C'est un peu drôle. Regardez mon ls:

ls -d ./*
./      ./          ./              ./                  ./                 
./      ./          ./              ./                  ./                  
./      ./          ./              ./                  ./                   
./      ./          ./              ./                  ./     

Maintenant, je vais refléter ce répertoire:

set -- * ; mkdir ../mirror
ls -i1qdU -- "$@" |
sh -c 'while read inum na
    do  ln -T "$1" ../mirror/$inum
    shift ; done' -- "$@"
ls -d ../mirror/*

Voici le contenu de ../mirror/:

../mirror/423759  ../mirror/423764  ../mirror/423769  ../mirror/423774
../mirror/423760  ../mirror/423765  ../mirror/423770  ../mirror/423775
../mirror/423761  ../mirror/423766  ../mirror/423771  ../mirror/423776
../mirror/423762  ../mirror/423767  ../mirror/423772  ../mirror/423777
../mirror/423763  ../mirror/423768  ../mirror/423773  ../mirror/423778

D'accord, mais vous demandez peut-être - mais à quoi ça sert? Comment savoir lequel est lequel? Comment pouvez-vous être sûr d'avoir lié le bon numéro d'inode au bon nom de fichier?

Bien...

echo "heyhey" >>./'    ' 
tgt=$(ls -id ./'    ')
cat ../mirror/${tgt%% .*} \
    $(ls -1td ../mirror/* | head -n1) 

PRODUCTION

heyhey
heyhey

Voir, le numéro d'inode contenu dans ../mirror/"${tgt%% .*}" Et celui référencé par ./' ' Font référence au même fichier. Ils décrivent le même fichier. Ils le nomment, mais rien de plus. Il n'y a pas de mystère, vraiment, juste quelques inconvénients que vous pourriez vous faire, mais qui auront finalement peu ou pas d'effet sur le fonctionnement de votre système de fichiers Unix à la fin.

2
mikeserv