¿Cómo hacer que bash ponga prompt en una nueva línea después del comando cat?

17

Lo que consigo:

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

Lo que quiero obtener:

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

¿Hay alguna manera de hacer que se catcomporte así?

Estoy usando bash en Mac OS X.

Stanislav Shabalin
fuente

Respuestas:

15

La mayoría de las herramientas de Unix están diseñadas para funcionar bien con archivos de texto. Un archivo de texto consta de una secuencia de líneas. Una línea consiste en una secuencia de caracteres imprimibles que terminan con un carácter de nueva línea. En particular, el último carácter de un archivo de texto no vacío es siempre un carácter de nueva línea. Evidentemente, example.txtsolo contienesome text sin nueva línea final, por lo que no es un archivo de texto.

cathace un trabajo simple; convertir archivos arbitrarios en archivos de texto no es parte de ese trabajo. Algunas otras herramientas siempre convierten su entrada en archivos de texto; Si no está seguro de que el archivo que está mostrando termina con una nueva línea, intente ejecutarawk 1 lugar de cat.

Puede hacer que el bash muestre su solicitud en la siguiente línea si el comando anterior dejó el cursor en algún lugar que no sea el último margen. Ponga esto en su .bashrc(variación por GetFree de una propuesta de Dennis Williamson ):

shopt -s promptvars
PS1='$(printf "%$((COLUMNS-1))s\r")'$PS1
Gilles 'SO- deja de ser malvado'
fuente
¡Muchas gracias por una solución de trabajo y una explicación sucinta! Entiendo que esto es un poco demasiado para los pobres cat, por lo que lo mantendré como último recurso para el momento en que este problema vuelva a molestarme.
Stanislav Shabalin
Dado que esta es la preferencia bash, ¿puede romper los comandos de tubería?
Stanislav Shabalin
1
@StanislavShabalin Esto no afecta las tuberías, solo el aviso.
Gilles 'SO- deja de ser malvado'
Necesito eliminar el "-1" después de "COLUMNAS" para que esto funcione correctamente.
rafak
Esta solución hace que el mensaje se mueva cuando se cambia el tamaño de la ventana del terminal. Descubrí que para que esto funcionara de manera confiable, tenía que ingresar la columna actual PROMPT_COMMANDy, si no es 0, usar una nueva línea ( \n) como primer carácter de PS1.
Brian Donovan
10

Prefiero el siguiente método ...

cat example.txt ; echo

Esto no evalúa el contenido de example.txt ni agrega ocasionalmente una nueva línea. Simplemente hace eco de una nueva línea una vez que el gato está listo, es fácil de recordar y nadie está pensando si está usando citas fuertes o débiles correctamente.

El único inconveniente, en realidad, es que obtendrá una nueva línea adicional si el archivo tiene su propia nueva línea final.

Amós
fuente
7

Comencé a usar la respuesta de @ Gilles, pero descubrí que si el terminal cambiaba el número de columnas, el mensaje ya no estaría al comienzo de una línea como se esperaba. Esto puede suceder por una variedad de razones, que incluyen divisiones de pantalla / tmux, cambio de tamaño manual de un contenedor de GUI, cambios de fuente, etc.

Lo que realmente quería era algo que agregaría una nueva línea si el terminal comenzara a imprimir su mensaje en algo diferente a la primera columna. Para hacer esto, necesitaba descubrir cómo obtener la columna actual, que utilicé para obtener esta respuesta . La configuración final del indicador de trabajo está a continuación:

###
# 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
fuente
Utilizo esta solución, pero cuando trato de pegar comandos de varias líneas en mi shell, parece terminar comiendo parte / todas las líneas después de pegar la primera. Hay alguna solución para esto?
solo el
@onlynone posiblemente sus comandos no se vacíen individualmente y a tiempo para __get_terminal_column?
Androbin
En lugar de PS1="\n"solo tengo echoy no necesito modificar PS1.
Androbin
4

El problema con eso podría ser que su example.txt no tiene una nueva línea al final de su archivo.

Bonsi Scott
fuente
2
La cuestión es que no me importa si el archivo tiene una nueva línea al final o no. Quiero poder ver la salida del gato más clara y no tan perjudicial :-) Y entiendo que no cates el trabajo, así que probablemente estoy buscando alguna solución.
Stanislav Shabalin
1
Esta es una respuesta que example.txtno tiene una nueva línea al final del archivo es el punto central de la pregunta.
Willem D'Haeseleer
2

Si insiste en usar cat, esto funciona para ambos tipos de archivos, con y sin una nueva línea al final:

echo "`cat example.txt`"

Puede convertirlo en una función con un nombre de su elección (incluso cat) en su .bashrc:

cat1(){ echo "`/bin/cat $@`";}
Dios de madera
fuente
1
Ahora eso es demasiado, incluso si funciona ;-) ¡Gracias de todos modos!
Stanislav Shabalin
0

puedes agregar a .bashrc también

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

funciona para mi.

Klaus
fuente
1
Esto también agregaría una línea en blanco adicional en el terminal cada vez que una utilidad genera algo que una nueva línea termina correctamente.
Kusalananda
Eso es verdad. Pero es simple, y si no te molesta tener una línea extra ...
Klaus