Comment faire bash mettre une invite sur une nouvelle ligne après la commande cat?

17

Ce que j'obtiens:

host:~ user$ cat example.txt
some texthost:~ stas$

Ce que je veux obtenir:

host:~ user$ cat example.txt
some text
host:~ stas$

Existe-t-il un moyen de faire en sorte que je me catcomporte comme ça?

J'utilise bash sur Mac OS X.

Stanislav Shabalin
la source

Réponses:

15

La plupart des outils Unix sont conçus pour bien fonctionner avec des fichiers texte. Un fichier texte se compose d'une séquence de lignes. Une ligne se compose d'une séquence de caractères imprimables se terminant par un caractère de nouvelle ligne. En particulier, le dernier caractère d'un fichier texte non vide est toujours un caractère de nouvelle ligne. Évidemment, example.txtcontient uniquement some textsans nouvelle ligne finale, il ne s'agit donc pas d'un fichier texte.

catfait un travail simple; transformer des fichiers arbitraires en fichiers texte ne fait pas partie de ce travail. Certains autres outils transforment toujours leur entrée en fichiers texte; si vous n'êtes pas sûr que le fichier que vous affichez se termine par une nouvelle ligne, essayez d'exécuter awk 1au lieu de cat.

Vous pouvez faire en sorte que bash affiche son invite sur la ligne suivante si la commande précédente a laissé le curseur ailleurs que dans la dernière marge. Mettez ceci dans votre .bashrc(variation par GetFree d'une proposition de Dennis Williamson ):

shopt -s promptvars
PS1='$(printf "%$((COLUMNS-1))s\r")'$PS1
Gilles 'SO- arrête d'être méchant'
la source
Merci beaucoup pour une solution de travail et une explication succincte! Je comprends que c'est un peu trop pour les pauvres cat, donc je vais garder cela en dernier recours pour le moment où ce problème recommence à me déranger.
Stanislav Shabalin
Puisqu'il s'agit d'une préférence bash, peut-elle interrompre les commandes de tuyauterie?
Stanislav Shabalin
1
@StanislavShabalin Cela n'affecte pas la tuyauterie, seulement l'invite.
Gilles 'SO- arrête d'être méchant'
J'ai besoin de supprimer le "-1" après "COLONNES" pour que cela fonctionne correctement.
rafak
Cette solution entraîne le déplacement de l'invite lorsque la fenêtre du terminal est redimensionnée. J'ai trouvé que pour que cela fonctionne de manière fiable, je devais insérer la colonne actuelle PROMPT_COMMANDet, si ce n'est pas 0, utiliser un newline ( \n) comme premier caractère de PS1.
Brian Donovan
10

Je préfère la méthode suivante ...

cat example.txt ; echo

Cela n'évalue pas le contenu example.txtou n'ajoute pas occasionnellement une nouvelle ligne. Il fait simplement écho à une nouvelle ligne une fois le chat terminé, est facile à retenir et personne ne se demande s'il utilise correctement les citations fortes ou faibles.

Le seul inconvénient est que vous obtiendrez une nouvelle ligne supplémentaire si le fichier a sa propre nouvelle ligne de fin.

Amos
la source
7

J'ai commencé à utiliser la réponse de @ Gilles, mais j'ai constaté que si le terminal changeait le nombre de colonnes, l'invite ne serait plus au début d'une ligne comme prévu. Cela peut se produire pour diverses raisons, notamment les divisions tmux / écran, le redimensionnement manuel d'un conteneur GUI, les changements de police, etc.

Ce que je voulais vraiment, c'était quelque chose qui ajouterait une nouvelle ligne si le terminal commençait à imprimer son invite à autre chose que la première colonne. Pour ce faire, j'avais besoin de comprendre comment obtenir la colonne actuelle, que j'ai utilisée pour obtenir cette réponse . La configuration finale de l'invite de travail est ci-dessous:

###
# Configure PS1 by using the old value but ensuring it starts on a new line.
###
__configure_prompt() {
  PS1=""

  if [ "$(__get_terminal_column)" != 0 ]; then
    PS1="\n"
  fi

  PS1+="$PS1_WITHOUT_PREPENDED_NEWLINE"
}

###
# Get the current terminal column value.
#
# From /programming//a/2575525/549363.
###
__get_terminal_column() {
  exec < /dev/tty
  local oldstty=$(stty -g)
  stty raw -echo min 0
  echo -en "\033[6n" > /dev/tty
  local pos
  IFS=';' read -r -d R -a pos
  stty $oldstty
  echo "$((${pos[1]} - 1))"
}

# Save the current PS1 for later.
PS1_WITHOUT_PREPENDED_NEWLINE="$PS1"

# Use our prompt configuration function, preserving whatever existing
# PROMPT_COMMAND might be configured.
PROMPT_COMMAND="__configure_prompt;$PROMPT_COMMAND"
Brian Donovan
la source
J'utilise cette solution, mais lorsque j'essaie de coller des commandes multi-lignes dans mon shell, il semble finir par manger une partie / toutes les lignes après la première collée. Y a-t-il une solution à cela?
seulement
@onlynone vos commandes ne sont peut-être pas vidées individuellement et à temps pour __get_terminal_column?
Androbin
Au lieu de PS1="\n"je viens echoet je n'ai pas besoin de modifier PS1.
Androbin
4

Le problème avec cela pourrait être que votre example.txt n'a pas de nouvelle ligne à la fin de votre fichier.

Bonsi Scott
la source
2
Le fait est que je me fiche que le fichier ait une nouvelle ligne à la fin ou non. Je veux être en mesure de voir la sortie de chat plus claire et non perturbatrice :-) Et je comprends que ce n'est pas catle travail, donc je cherche probablement une solution.
Stanislav Shabalin
1
C'est une telle non-réponse example.txtne pas avoir une nouvelle ligne à la fin du fichier est tout le point de la question.
Willem D'Haeseleer
2

Si vous insistez sur l'utilisation cat, cela fonctionne pour les deux types de fichiers, avec et sans retour à la ligne à la fin:

echo "`cat example.txt`"

Vous pouvez le transformer en fonction avec un nom de votre choix (pair cat) dans votre .bashrc:

cat1(){ echo "`/bin/cat $@`";}
woodengod
la source
1
Maintenant c'est un peu trop, même si ça marche ;-) Merci quand même!
Stanislav Shabalin
0

vous pouvez également ajouter à .bashrc

PROMPT_COMMAND="printf '\n';$PROMPT_COMMAND"

travaille pour moi.

Klaus
la source
1
Cela ajouterait également une ligne vierge supplémentaire dans le terminal chaque fois qu'un utilitaire sort quelque chose qui est correctement terminé par une nouvelle ligne.
Kusalananda
C'est vrai. Mais c'est simple, et si cela ne vous dérange pas d'avoir une ligne supplémentaire ...
klaus