web-dev-qa-db-fra.com

La redirection avec ">>" est-elle équivalente à ">" lorsque le fichier cible n'existe pas encore?

Considérons un Shell comme Bash ou sh. La différence fondamentale entre > et >> se manifeste dans le cas où le fichier cible existe:

  • > tronque le fichier à la taille zéro, puis écrit;
  • >> ne tronque pas, il écrit (ajoute) à la fin du fichier.

Si le fichier n'existe pas, il est créé avec une taille nulle. puis écrit à. Ceci est vrai pour les deux opérateurs. Il peut sembler que les opérateurs sont équivalents lorsque le fichier cible n'existe pas encore.

Sont-ils vraiment?

80
Kamil Maciorowski

tl; dr

Non. >> est essentiellement "chercher toujours à la fin du fichier", alors que > conserve un pointeur sur le dernier emplacement écrit.


Réponse complète

(Remarque: tous mes tests ont été effectués sur Debian GNU/Linux 9).

Une autre différence

Non, ils ne sont pas équivalents. Il y a un autre différence. Il peut se manifester indépendamment du fait que le fichier cible existait auparavant ou non.

Pour l'observer, exécutez un processus qui génère des données et redirigez-le vers un fichier avec > ou >> (par exemple pv -L 10k /dev/urandom > blob). Laissez-le fonctionner et modifiez la taille du fichier (par exemple, avec truncate). Vous verrez que > conserve son offset (en croissance) alors que >> est toujours ajouté à la fin.

  • Si vous tronquez le fichier à une taille plus petite (la taille peut être nulle)
    • > ne s'en souciera pas, il écrira à l'offset souhaité comme si de rien n'était; juste après que la troncature du décalage dépasse la fin du fichier, le fichier retrouvera son ancienne taille et s'agrandira davantage, les données manquantes seront remplies de zéros (de manière réduite, si possible);
    • >> sera ajouté à la nouvelle fin, le fichier passera de sa taille tronquée.
  • Si vous agrandissez le fichier
    • > ne s'en souciera pas, il écrira à l'offset souhaité comme si de rien n'était; juste après avoir changé la taille de l'offset se trouvant quelque part dans le fichier, le fichier cessera de croître pendant un certain temps, jusqu'à ce que l'offset atteigne la nouvelle fin, puis le fichier s'agrandira normalement;
    • >> sera ajouté à la nouvelle fin, le fichier grandira à partir de sa taille agrandie.

Un autre exemple consiste à ajouter (avec un >> séparé) quelque chose de plus lorsque le processus de génération de données est en cours d'exécution et en écriture dans le fichier. Ceci est similaire à l’agrandissement du fichier.

  • Le processus de génération avec > écrira à l'offset souhaité et écrasera éventuellement les données supplémentaires.
  • Le processus de génération avec >> ignorera les nouvelles données et les ajoutera au-delà (des conditions de concurrence peuvent se produire, les deux flux peuvent être entrelacés, aucune donnée ne doit être écrasée).

Exemple

Est-ce important dans la pratique? Il y a cette question :

J'exécute un processus qui produit beaucoup de sortie sur stdout. Tout envoyer dans un fichier [...] Puis-je utiliser un type de programme de rotation des journaux?

Cette réponse indique que la solution est logrotate avec l'option copytruncate qui agit comme ceci:

Tronquez le fichier journal d'origine en place après avoir créé une copie, au lieu de déplacer l'ancien fichier journal et éventuellement d'en créer un nouveau.

D'après ce que j'ai écrit ci-dessus, la redirection avec > rendra le journal tronqué volumineux en un rien de temps. La rareté permettra de sauver la journée, aucun espace disque important ne doit être gaspillé. Néanmoins, chaque journal consécutif comportera de plus en plus de zéros non nécessaires.

Cependant, si logrotate crée des copies sans préserver l’éparpillement, ces zéros non hiérarchiques auront besoin de plus en plus d’espace disque à chaque copie. Je n'ai pas étudié le comportement de l'outil, il est peut-être assez intelligent en cas d'écartement ou de compression à la volée (si la compression est activée). Cependant, les zéros ne peuvent que causer des problèmes ou être au mieux neutres; rien de bon en eux.

Dans ce cas, utiliser >> au lieu de > est nettement préférable, même si le fichier cible est sur le point d'être créé.


Performance

Comme on peut le constater, les deux opérateurs agissent différemment non seulement au début mais aussi plus tard. Cela peut entraîner des différences de performances (subtiles?). Pour l'instant, je n'ai aucun résultat de test significatif pour le confirmer ou le réfuter, mais je pense que vous ne devriez pas automatiquement présumer que leurs performances sont identiques en général.

106
Kamil Maciorowski