Erzwingen Sie Zeilenumbrüche beim Drucken von Katzen-Platzhaltern

9

Ich möchte cat mit Platzhaltern in bash verwenden, um mehrere kleine Dateien (jede Datei besteht aus einem Satz) in die Standardausgabe zu drucken. Der separate Dateiinhalt wird jedoch nicht durch einen Zeilenumbruch getrennt, den ich zur besseren Lesbarkeit verwenden möchte.

Wie kann ich diesem Befehl einen Dateibegrenzer hinzufügen?

lennyklb
quelle

Antworten:

12

Definieren Sie eine Shell-Funktion, die nach jeder Datei ein Zeilenende ausgibt, und verwenden Sie sie anstelle von cat:

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

dann kannst du verwenden endlcat *.

Die forSchleife durchläuft alle bereitgestellten Argumente ( $@), die bereits von der Shell maskiert werden, wenn Sie Platzhalter wie verwenden *. Das --ist erforderlich, um Dateinamen, die mit einem Bindestrich beginnen, nicht zu ersticken. Schließlich echogibt das eine neue Zeile aus.

Marco
quelle
Es scheint ziemlich offensichtlich, Iteration im Nachhinein zu verwenden! Ich dachte, es könnte eine Flagge in der Katze gegeben haben, aber das funktioniert auch! Vielen Dank.
Lennyklb
Sie brauchen das nicht in "$@"- es ist implizit.
10b0
4
explizit zu sein ist gut für die Lesbarkeit.
Cas
5

Verwenden Sie einfach eine Schleife anstelle von einfach cat:

for file in /path/to/targetdir/*; do
    echo "-------- $file -------"
    cat "$file" 
done
terdon
quelle
Funktioniert wie die akzeptierte Antwort, aber diese hatte auch den nächsten Schritt zur Kommandozeile, also habe ich die andere akzeptiert.
Lennyklb
3

Wenn Sie einen Dateinamen zwischen Dateien wünschen, verwenden Sie tail:

tail -n +1 ./*

(Falls Sie tacstattdessen möchten cat, haben einige tailImplementierungen die -rOption für eine gleichwertige tacFunktion.)

cuonglm
quelle
3

Das wird funktionieren:

sed '' -- *

Sie benötigen keine Shell-Schleifen oder \nähnliches , und dies folgt immer der Ausgabe einer Datei mit einer Ewline - mit Ausnahme der allerletzten.

Andernfalls könnte dies funktionieren, wenn zwischen den Ausgaben jeder Datei eine leere Zeile ausgegeben werden soll:

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

\nDies folgt immer der Ausgabe einer Datei mit einer Ewline und einer zusätzlichen Leerzeile .

Sie können es so nennen:

bpaste *
mikeserv
quelle
@cuonglm - Die Operation möchte eine neue Zeile zwischen den Dateien. Dies stellt eine neue Zeile zwischen den Dateien sicher.
Mikesserv
@ Cuonglm - Sie sollten es erneut versuchen. for n in 1 2 3; do printf "$n" >"$n"; done; sed '' -- [123]
Mikesserv
@cuonglm - Jeder sedmuss immer eine \nEwline drucken, bevor etwas anderes gedruckt wird. In der letzten Zeile der letzten Datei wird jedoch möglicherweise keine \nEwline angehängt. Ich könnte schwören, dass ich diese Frage schon einmal beantwortet habe.
Mikesserv
@ Cuonglm - Ich verstehe nicht, was du meinst. Das kleine Stück Muschel, das ich dir gerade gegeben habe 1\n2\n3. Es klappt. das tut es immer. Was druckt es für Sie?
Mikesserv
1
@ TennisWilliamson: Die Verwendung \nin RHS ist nicht Standard. Sie können verwenden sed -e '$G'.
Cuonglm
2

Ähnlich wie bei @terdons Antwort können Sie den folgenden headBefehl verwenden , wenn Sie den Dateinamen auch in Zukunft bevorzugen.

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

==> file_2 <==
file 2 content

==> file_3 <==
file 3 content

headDer Standardwert sind die ersten 10 Zeilen. Daher ist die Verwendung ohne Befehlsoptionen für Ihren Fall (ein Satz pro Datei) vollkommen in Ordnung. Andernfalls benötigen Sie die -n XOption.

hjk
quelle
2

Eine andere Möglichkeit - verwenden Sie grep -hdiese Option, um einfach in jeder Datei nach der leeren Zeichenfolge zu suchen. Dies entspricht allen Zeilen, unabhängig davon, wie viele oder ob Zeilenumbrüche abgeschlossen sind oder nicht. grep-Ergebnisse werden immer mit Zeilenumbruch beendet. Die -hOption unterdrückt das Präfixieren jeder Ausgabezeile mit dem Dateinamen, von dem sie stammt:

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

Oder Sie können GNU pasteim -sErial-Modus mit Newline als Trennzeichen verwenden:

$ paste -s -d '\n' -- *
a
b
B
c
$ 
Digitales Trauma
quelle