Forcer les nouvelles lignes avec l'impression générique de chat

9

Je veux utiliser cat avec des caractères génériques dans bash afin d'imprimer plusieurs petits fichiers (chaque fichier est une phrase) sur la sortie standard. Cependant, le contenu du fichier séparé n'est pas séparé par une nouvelle ligne, ce que j'aimerais pour faciliter la lecture.

Comment puis-je ajouter un délimiteur de fichier quelconque à cette commande?

lennyklb
la source

Réponses:

12

Définissez une fonction shell qui génère une fin de ligne après chaque fichier et utilisez-la à la place de cat:

endlcat() {
  for file in "$@"; do
    cat -- "$file"
    echo
  done
}

alors vous pouvez utiliser endlcat *.

La forboucle boucle sur tous les arguments fournis ( $@) qui sont déjà échappés par le shell lorsque vous utilisez des caractères génériques comme *. Le --est requis pour ne pas s'étouffer avec les noms de fichiers commençant par un tiret. Enfin, la echosortie d'une nouvelle ligne.

Marco
la source
Il semble assez évident d'utiliser l'itération avec le recul! Je pensais qu'il y avait peut-être un drapeau chez le chat, mais ça marche aussi! Je vous remercie.
lennyklb
Vous n'avez pas besoin de in "$@"- c'est implicite.
l0b0
4
être explicite est bon pour la lisibilité.
cas
5

Utilisez simplement une boucle au lieu de simple cat:

for file in /path/to/targetdir/*; do
    echo "-------- $file -------"
    cat "$file" 
done
terdon
la source
Fonctionne comme la réponse acceptée, mais celle-ci avait également l'étape suivante vers la ligne de commande, j'ai donc accepté l'autre.
lennyklb
3

Si vous voulez un nom de fichier entre les fichiers, utilisez tail:

tail -n +1 ./*

(Au cas où vous voudriez tacau lieu de cat, certaines tailimplémentations ont une -roption pour une tacfonctionnalité équivalente )

cuonglm
la source
3

Cela fonctionnera:

sed '' -- *

Vous n'avez pas besoin de boucles shell ou autre, et cela suivra toujours la sortie d'un fichier avec une ligne \nélectronique - à l'exception peut-être de la toute dernière.

Sinon, si vous voulez qu'une ligne vide soit sortie entre la sortie de chaque fichier, cela pourrait fonctionner:

bpaste(){
    eval "paste -'sd\n' -- $(x=0;for f do printf "\"\${$((x+=1))}\" - ";done)"
}   </dev/null

Cela suivra toujours la sortie d'un fichier avec une ligne \nélectronique et une ligne vierge supplémentaire .

Vous pouvez l'appeler comme:

bpaste *
mikeserv
la source
@cuonglm - l'op veut une nouvelle ligne entre les fichiers. cela garantit une nouvelle ligne entre les fichiers.
mikeserv
@cuonglm - vous devriez réessayer. for n in 1 2 3; do printf "$n" >"$n"; done; sed '' -- [123]
mikeserv
@cuonglm - tout seddoit toujours imprimer une ligne \nélectronique avant d'imprimer quoi que ce soit d'autre, la dernière ligne du dernier fichier peut ne pas être \najoutée à une ligne électronique. je pourrais jurer ive répondu à cette question avant.
mikeserv
@cuonglm - je ne comprends pas ce que vous voulez dire. ce petit morceau de coquille que je viens de vous donner des impressions 1\n2\n3. Ça marche. c'est toujours le cas. qu'est-ce que cela imprime pour vous?
mikeserv
1
@DennisWilliamson: L'utilisation \nen RHS n'est pas standard. Vous pouvez utiliser sed -e '$G'.
cuonglm
2

Semblable à la réponse de @terdon , si vous préférez également voir le nom de fichier à l'avenir, vous pouvez utiliser la headcommande:

$ head *file*
==> file_1 <==
file 1 content

==> file_2 <==
file 2 content

==> file_3 <==
file 3 content

headla valeur par défaut est les 10 premières lignes, donc l'utiliser sans options de commande pour votre cas (une phrase par fichier) est tout à fait correct. Sinon, vous avez besoin de l' -n Xoption.

hjk
la source
2

Une autre façon - utilisez grep -hpour rechercher simplement la chaîne vide dans chaque fichier. Cela correspondra à toutes les lignes, quel que soit leur nombre ou qu'elles se terminent par une nouvelle ligne ou non. les résultats de grep se terminent toujours par une nouvelle ligne. L' -hoption supprime le préfixe de chaque ligne de sortie avec le nom de fichier dont elle provient:

$ printf 'a' > a
$ printf 'b\nB' > b
$ printf 'c\n' > c
$ ls
a  b  c
$ cat -- *
ab
Bc
$ grep -h '' *
a
b
B
c
$ 

Ou vous pouvez utiliser GNU pasteen -smode erial avec newline comme délimiteur:

$ paste -s -d '\n' -- *
a
b
B
c
$ 
Traumatisme numérique
la source