2010-10-09 8 views
12

J'écris une application qui agit comme un filtre: elle lit l'entrée d'un fichier (stdin), traite et écrit la sortie dans un autre fichier (stdout). Le fichier d'entrée est complètement lu avant que l'application commence à écrire le fichier de sortie.Utiliser le même fichier pour stdin et stdout avec redirection

Depuis que je suis en utilisant stdin et stdout, je peux courir est comme ceci:

$ ./myprog <file1.txt >file2.txt 

Il fonctionne très bien, mais si je tente d'utiliser le même fichier que l'entrée et la sortie (qui est: lire à partir un fichier et écrire dans le même fichier), comme ceci:

$ ./myprog <file.txt >file.txt 

il nettoie file.txt avant que le programme a la chance de le lire.

Est-il possible de faire quelque chose comme ça dans une ligne de commande sous Unix?

Répondre

13

Le shell est ce qui clobbers votre fichier de sortie, car il prépare les fichiers de sortie en sortie avant en exécutant votre programme. Il n'y a aucun moyen de faire en sorte que votre programme lise l'entrée avant que le shell n'obstrue le fichier dans une ligne de commande à un seul shell.

Vous devez utiliser deux commandes, soit déplacer ou copier le fichier avant de le lire:

mv file.txt filecopy.txt 
./myprog <filecopy.txt> file.txt 

Ou sortir d'autre à une copie, puis remplacer l'original:

./myprog <file.txt> filecopy.txt 
mv filecopy.txt file.txt 

Si vous le pouvez Ne faites pas cela, alors vous devez passer le nom de fichier à votre programme, ce qui ouvre le fichier en mode lecture/écriture, et gère toutes les E/S en interne.

./myprog file.txt     # reads and writes according to its own rules 
8

Pour une solution de nature purement académique:

$ (unlink file.txt && ./myprog >file.txt) <file.txt 

effets secondaires problématiques sont Peut-être:

  • Si ./myprog échoue, vous détruisez votre entrée. (Bien entendu ...)
  • ./myprog fonctionne à partir d'un sous-shell (utilisation { ... ; } au lieu de (...) éviter.)
  • file.txt devient un nouveau fichier avec une nouvelle autorisations inode et fichiers.
  • Vous avez besoin de l'autorisation +w sur le logement de répertoire file.txt.
+0

Étrange. Pourquoi '$ (./myprog> file.txt) TheoYou

+0

Votre exemple le fait car '> file.txt' tronque le contenu de file.txt et c'est d'ailleurs le même fichier que' fichier.txt' crée un * nouveau fichier * (inode différent sur le même chemin) séparé de ce que ' antak

+0

Donc, tout ce que nous avons à faire est de lancer la sous-shell nous-mêmes. Je pense que je connais la réponse, mais je ne sais toujours pas pourquoi ... – TheoYou

15

Il y a un utilitaire éponge dans moreutils package:

./myprog < file.txt | sponge file.txt 

Pour citer le manuel:

éponge lit l'entrée standard et l'écrit sur le fichier spécifié. Contrairement à une redirection shell, l'éponge absorbe toutes ses entrées avant d'ouvrir le fichier de sortie. Cela permet de construire des pipelines qui lisent et écrivent dans le même fichier.

+1

S'il vous plaît, développez votre réponse. – Beppe

Questions connexes