2
votes

Lire un fichier ligne par ligne sur bash; chaque ligne contenant le chemin vers un autre fichier unqiue

Chaque ligne d'un fichier donné ' a.txt ' contient le répertoire / chemin vers un autre fichier unique. Supposons que nous voulions analyser « a.txt » ligne par ligne, extraire le chemin au format chaîne, puis utiliser un outil tel que vim pour traiter le fichier à ce chemin, et ainsi de suite.

Après avoir parcouru ce fil de discussion - Lire un fichier ligne par ligne en attribuant la valeur à une variable , j'ai écrit le script suivant, disons ' open-file.sh ' sur bash (je suis nouveau)

./open-file.sh a.txt

Nous exécuterions alors le script ci-dessus comme -

#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
  vim -c ":q" -cq $line # Just open the file and close it using :q 
done < "$1"

Le problème est que, bien que le chemin vers un nouveau fichier soit correctement spécifié par $ line, lorsque vim ouvre le fichier, vim continue de recevoir le texte contenu dans ' a.txt ' en tant que commande. Comment puis-je écrire un script où je peux obtenir correctement le chemin à partir de ' a.txt ', l'ouvrir à l'aide de vim, puis continuer à analyser les lignes restantes dans ' a.txt em > '?


0 commentaires

3 Réponses :


2
votes

Remplacer:

vim -c ":q" -cq "$line" </dev/tty

Avec:

vim -c ":q" -cq $line

La redirection dev / tty indique vim pour prendre son entrée standard du terminal. Sans cela, l'entrée standard pour vim est "$1".

De plus, il est recommandé de mettre $ line code > entre guillemets pour le protéger du partage de mots , etc.

Enfin, alors que vim est excellent pour le travail interactif, si votre objectif est un traitement entièrement automatisé de chaque fichier, vous pourriez envisager des outils tels que sed ou awk.


1 commentaires

Je vérifierai les autres outils que vous avez mentionnés.



0
votes

Bien que je ne sois pas sûr de votre objectif ultime, cette commande shell exécutera vim une fois par ligne dans a.txt :

xargs -o -n1 vim -c ': q'

Comme expliqué dans les commentaires sur Lire un fichier ligne par ligne en attribuant la valeur à une variable , le problème que vous rencontrez est dû au fait que vim est un programme interactif et continue donc à lire l'entrée de $ line .


4 commentaires

xargs -o n'est pas disponible dans mon GNU findutils 4.7.0 . D'après man xargs , il semble que -o soit spécifique à BSD. Citation: xargs sh -c 'emacs "$ @" [...] Cet exemple produit le même effet que BSD - o option, mais de manière plus flexible et portable.


Intéressant et bon à connaître. J'utilise également GNU findutils 4.7.0 sur Ubuntu et la page de manuel indique que -o a été ajouté pour une meilleure compatibilité avec BSD.


C'est étrange. La version complète est xargs (GNU findutils) 4.7.0-git Copyright (C) 2016 [...] . Je suis sur Ubuntu 16.04.3 LTS dans le sous-système Windows pour Linux (WSL). Lorsque j'essaie d'exécuter la commande, j'obtiens xargs: option invalide - 'o' .


Je suis sur Ubuntu 18.04, donc je suppose qu'ils l'ont ajouté assez récemment.



0
votes

Le problème était déjà mentionné dans un commentaire sous la réponse sur laquelle vous avez basé votre script.

vim consomme stdin qui est donné à la boucle par done . Nous pouvons observer le même comportement dans l'exemple suivant:

< "$1" xargs -d\\n -n1 vim -c :q -cq

simule un fichier avec les trois lignes 1 , 2 et 3 . Au lieu de trois itérations silencieuses, nous n'obtenons qu'une seule itération et la sortie 2 et 3.

stdin n'est pas seulement passée à read dans la tête de la boucle, mais aussi à cat dans le corps de la boucle. Par conséquent, read lit une ligne, la boucle est entrée, cat lit toutes les lignes restantes, stdin est vide, read n'a plus rien à lire, la boucle se termine.

Vous pouvez contourner le problème en redirigeant quelque chose vers vim , mais il existe un moyen encore meilleur. Vous n'avez pas du tout besoin de la boucle:

$ while read i; do cat; done < <(seq 3)
2
3

xargs exécutera vim une fois pour chaque ligne du fichier donné par $1.


1 commentaires

Ah oui, la réponse était dans le commentaire.