Comment parcourir des fichiers dans un répertoire puis les lire dans une variable de chaîne dans bash

J’essaie de parcourir un répertoire avec quelques fichiers .txt en bash. J’ai très peu d’expérience avec bash mais je dois l’utiliser parce que je peux exécuter d’autres commandes une fois que j’obtiens le contenu de chaque fichier. Je veux faire ça:

for file in ; do read its contents do something with the contents done 

J’ai trouvé que pour lire un fichier, vous pouvez le faire avec un fichier si je code le nom du fichier:

 contents = $(<filename.txt) 

et pour parcourir tous les fichiers d’un répertoire que je fais ceci:

 for file in dir; do done 

Je veux pouvoir parcourir tous les fichiers et les lire avec la variable de fichier dans la boucle. Mais à l’intérieur de la boucle, rien de tout cela ne fonctionne (j’ai essayé des combinaisons de ceux-ci également):

 for file in dir; do contents = $(<$file) done for file in dir; do contents = $(<"$file") done for file in dir; do contents = $(<${file##*/}) done for file in dir; do contents = $(<"${file##*/}") done for file in dir; do contents = $(<$(basename "$file")) done for file in dir; do filename = $(basename "$file") contents = $(<$filename) done for file in dir; do filename = "${file##*/}" contents = $(<$filename) done 

Merci d’avance pour votre aide.

 find  -iname '*.txt' -exec cat {} + | your_parser 

ou juste

 cat //*.txt | your_parser 

La plus grande question est de savoir si vous avez vraiment besoin de lire le contenu de chaque fichier d’intérêt dans une variable shell, mais pour y parvenir, le principal problème avec vos tentatives était que vous aviez des espaces autour du signe = ‘t supporté

Quelque chose comme contents = ... (notez les espaces autour de = ) fera croire au shell que vous exécutez une commande nommée contents , qui échoue.

Ainsi, avec ce problème fixe et la double citation des variables ajoutées pour la robustesse, les éléments suivants devraient fonctionner:

 dir='.' # sample target dir for file in "$dir"/*.txt; do contents=$(<"$file") # read contents of file $file # ... work with "$contents" done 

Vous pouvez faire quelque chose comme ci-dessous, en utilisant la process substitution <()

 #!/bin/bash while IFS= read -r -d '' file do # Your other actions on the files go here. The `-print0` option in # find command helps identify all zip files even with special characters # in them. # The bash variable "$file" holds the zip file name which you an use in printf "%s\n%s\n" "Contents of $file:-" "$( 

Par exemple, nous supposerons que file1.txt contient “texta”, file2.txt contient “text b” et file3.txt contient “textc”. Le texte dans file2.txt contient un espace.

Si les fichiers sont des fichiers d’une seule ligne ou si vous n’avez pas besoin de travailler sur chaque ligne individuellement, votre boucle for est à peu près complète.

 for file in dir/*; do contents="$contents $(<"$file")" done 

Cependant, cela crée une seule ligne, chaque entrée de fichier étant divisée par espaces. Selon la manière dont la variable est utilisée ultérieurement, cela peut entraîner des problèmes. Les espaces à l'intérieur des fichiers et les espaces entourant chaque entrée sont indiscriminés

 #Value of $contents: texta text b textc 

Vous pouvez à la place diviser chaque texte de fichier dans une nouvelle ligne en utilisant;

 contents="$contents\n$(<"$file")" #Value of $contents: texta text b textc 

Mais le même problème se produirait si vos fichiers texte contiennent plusieurs lignes elles-mêmes.

Vous pouvez également diviser le texte de chaque fichier en un index séparé dans un tableau.

 contents+=("$(<"$file")") 

Avec un tableau, chaque entrée peut être référencée avec $ {contents [$ i]}, où $ i est le numéro d'index.

 #Value of ${contents[0]} texta #Value of ${contents[1]} text b #Value of ${contents[2]} textc #Value of $(contents[*]} is all indexes. Listed values are automatically separated by a space. texta text b textc 

Vous pouvez bien sûr également ne pas faire de séparation,

 contents="$contents$(<"$file")" #Value of $contents: textatext btextc 

-

Cela étant dit, si vous devez diviser les fichiers par ligne, chaque ligne de chaque fichier étant séparée, vous pouvez le faire avec une boucle while intégrée.

 for file in dir; do while read line; do contents="$contents $(<"$line")" done <$file done 

Cela exécute la boucle while une fois par fichier trouvé dans la boucle for. Encore une fois, la ligne d'affectation de variables peut être remplacée par l'une des autres méthodes, selon les besoins.