awk
, sed
, and perl
, as presented in the other answers, excel at text processing and are probably the best tools for the job.
But you can also do this in pure bash
(i.e., "without leaving the shell"), if you like:
n=70
while read -r; do
if ((${#REPLY}<=n))
then printf '%s\n' "$REPLY"
else printf '%s...\n' "${REPLY:0:$((n-3))}"
fi
done < filename
Replace 70
with the maximum desired length, and filename
with the input file.
To use this on the right side of a pipe (i.e., to pipe another command's output to it), remove < filename
and either set n
beforehand or enclose the whole thing in { ... ;}
:
{ n=70
while read -r; do
if ((${#REPLY}<=n))
then printf '%s\n' "$REPLY"
else printf '%s...\n' "${REPLY:0:$((n-3))}"
fi
done ;}
(This bracket-enclosed version also works fine in other contexts, including with redirection as above. The brackets are unnecessary in that use case, but not harmful.)
This looks like:
ek@Ilex:~$ help read | head -5 | { n=70
> while read -r; do
> if ((${#REPLY}<=n))
> then printf '%s\n' "$REPLY"
> else printf '%s...\n' "${REPLY:0:$((n-3))}"
> fi
> done ;}
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N n...
Read a line from the standard input and split it into fields.
Reads a single line from the standard input, or from file descr...
if the -u option is supplied. The line is split into fields as...
Note that, in common with the other solutions that have been presented so far, this will fail to perfectly limit output width in the presence of characters that display more than one column wide, such as horizontal tabs.
...
or the single character…
?