If I have really long output from a command (single line) but I know I only want the first [x] (let's say 8) characters of the output, what's the easiest way to get that? There aren't any delimiters.
8 Answers
One way is to use cut
:
command | cut -c1-8
This will give you the first 8 characters of each line of output. Since cut
is part of POSIX, it is likely to be on most Unices.

- 46,160
These are some other ways to get only first 8 characters.
command | head -c8
command | awk '{print substr($0,1,8);exit}'
command | sed 's/^\(........\).*/\1/;q'
And if you have bash
var=$(command)
echo ${var:0:8}

- 919
-
3I think the following sed formulation is a bit easier to read:
command | sed 's/\(.\{8\}\).*/\1/'
or if your sed supports it:command | sed -r 's/(.{8}).*/\1/'
; Otherwise, +1 – Steven D Oct 24 '10 at 04:48 -
2Good stuff, but note that
head -c
counts bytes, not characters. Similarly, among the major Awk implementations, only GNU awk handles multi-byte characters correctly - FreeBSD Awk and Mawk do not. – mklement0 Jul 05 '15 at 17:30
Another one liner solution by using Shell parameter expansion
echo ${word:0:x}
EG: word="Hello world"
echo ${word:0:3} or echo ${word::3}
o/p: Hel
EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell

- 343
- 3
- 5
-
1You can also use a variable holding the length, e.g.:
x=8; echo ${word:0:$x}
instead of hard-coding the integer. – Cometsong Apr 25 '19 at 14:58 -
-
1@Cometsong Testing with the Bash shell that came with "Git for Windows", it looks like you don't need to prefix x with the $ sign in this case:
– AJM Mar 26 '21 at 11:10x=8; echo ${word:0:x}
will work the same. -
-
If you have a sufficiently advanced shell (for example, the following will work in Bash, not sure about dash), you can do:
read -n8 -d$'\0' -r <(command)
After executing read ... <(command)
, your characters will be in the shell variable REPLY
. Type help read
to learn about other options.
Explanation: the -n8
argument to read
says that we want up to 8 characters. The -d$'\0'
says read until a null, rather than to a newline. This way the read will continue for 8 characters even if one of the earlier characters is a newline (but not if its a null). An alternative to -n8 -d$'\0'
is to use -N8
, which reads for exactly 8 characters or until the stdin reaches EOF. No delimiter is honored. That probably fits your needs better, but I don't know offhand how many shells have a read that honors -N
as opposed to honoring -n
and -d
. Continuing with the explanation: -r
says ignore \
-escapes, so that, for example, we treat \\
as two characters, rather than as a single \
.
Finally, we do read ... <(command)
rather than command | read ...
because in the second form, the read is executed in a subshell which is then immediately exited, losing the information you just read.
Another option is to do all your processing inside the subshell. For example:
$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>

- 2,698
-
1If you just want to output the 8 chars, and don't need to process them in the shell, then just use
cut
. – dubiousjim Sep 08 '12 at 14:04 -
Good to know about
read -n <num>
; small caveat: Bash 3.x (still current on OS) mistakenly interprets<num>
as a byte count and thus fails with multi-byte characters; this has been fixed in Bash 4.x. – mklement0 Jul 06 '15 at 01:41 -
This is a great and useful answer. Much more general than the others. – not2qubit Oct 25 '19 at 10:08
-
On my git bash, I have the "-N" flag, which reads exactly N chars until EOF or timeout. Isn't that what you try to achieve your "d" flag ? – Itération 122442 May 03 '22 at 08:16
-
@Itération122442 yes but as I wrote "I don't know offhand how many shells have a read that honors -N as opposed to honoring -n and -d." – dubiousjim May 04 '22 at 09:43
-
-
-d$'\0'
is the same as-d
in bash. bash doesn't support passing NULs to commands, even builtin ones. You'd need-d ''
.-d ""
,-d $''
,-d $'\0'
,-d $'\u0000'
,-d $'\x0'
,-d $'\0\0\0\0'
would also work but they're all the same in bash, so using those\0
s there would be misleading. See also my answer for hints at other problems in that code. – Stéphane Chazelas Oct 05 '23 at 09:47
This is portable:
a="$(command)" # Get the output of the command.
b="????" # as many ? as characters are needed.
echo ${a%"${a#${b}}"} # select that many chars from $a
To build a string of variable length of characters has its own question here.
I had this problem when manually generating checksum files in maven repository.
Unfortunately cut -c
always prints out a newline at the end of output.
To suppress that I use xxd
:
command | xxd -l$BYTES | xxd -r
It outputs exactly $BYTES
bytes, unless the command
's output is shorter, then exactly that output.
-
another method to take off
cut
's trailing newline is to pip it into:| tr -d '\n'
– Cometsong Apr 25 '19 at 15:00
How to consider Unicode + UTF-8
Let's do a quick test for those interested in Unicode characters rather than just bytes. Each character of áéíóú
(acute accented vowels) is made up of two bytes in UTF-8. With:
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'
printf 'áéíóú' | LC_CTYPE=C awk '{print substr($0,1,3);exit}'
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 head -c3
echo
printf 'áéíóú' | LC_CTYPE=C head -c3
echo
we get:
áéí
á
á
á
so we see that only awk
+ LC_CTYPE=en_US.UTF-8
considered the UTF-8 characters. The other approaches took only three bytes. We can confirm that with:
printf 'áéíóú' | LC_CTYPE=C head -c3 | hd
which gives:
00000000 c3 a1 c3 |...|
00000003
and the c3
by itself is trash, and does not show up on the terminal, so we saw only á
.
awk
+ LC_CTYPE=en_US.UTF-8
actually returns 6 bytes however.
We could also have equivalently tested with:
printf '\xc3\xa1\xc3\xa9\xc3\xad\xc3\xb3\xc3\xba' | LC_CTYPE=en_US.UTF-8 awk '{print substr($0,1,3);exit}'
and if you want a general parameter:
n=3
printf 'áéíóú' | LC_CTYPE=en_US.UTF-8 awk "{print substr(\$0,1,$n);exit}"
Question more specific about Unicode + UTF-8: https://superuser.com/questions/450303/unix-tool-to-output-first-n-characters-in-an-utf-8-encoded-file
Tested on Ubuntu 21.04.

- 18,092
- 4
- 117
- 102
With zsh
, you can do:
cmd | read -u0 -k4 -e
read
will read as many bytes as needed to read 4 characters (k
was initially for k
ey, but with -u
specifying a file descriptor it reads characters from there instead of key presses from the terminal) and echo (-e
) those characters on stdout. You can change -e
to a variable name to read those bytes into a variable.
ksh93
later (in ksh93o in 2003, while zsh's -k
is from the 90s) added a -N
options as an equivalent of zsh
's -k
which was later copied by bash
(though with some differences, see below). It doesn't have an equivalent for -e
though.
cmd | read -N4 var
Contrary to zsh
, ksh93
cannot store NUL characters in its variables, and more generally, it will fail in random ways if there are NULs in its input.
Now, besides -N
, ksh93
also has a -n x
option which reads up to x
characters from a line, and the record delimiter can be changed with -d
, and with recent versions of ksh93u+m, -d ''
is for NUL-delimited records.
So:
cmd | read -d '' -n 4
there fails in a less random way if the input contains NUL characters: it just stops at the first NUL.
Now, bash copied all of -n
, -N
, -d
(including -d ''
) from ksh93 but with important differences:
- it still does backslash processing when
-n
/-N
are specified, so you need-r
to work around it as usual. - it still does
IFS
processing, which you need to work around by calling it asIFS= read...
as usual - it skips all NUL characters in its input
- by default, the last component of a pipeline also runs in a subshell, which you can work around by using a redirection to a process substitution.
So in bash, you'd do:
IFS= read -rN4 var < <(cmd)
To read the first non-NUL characters of the output of cmd
or (if cmd
is cat /dev/zero
, it will never return). And:
IFS= read -d '' -rn4 var < <(cmd)
To read 4 characters up to the first NUL.

- 544,893
cut -c
selects characters;cut -b
orhead -c
selects bytes. This makes a difference in some locales (in practice, when using UTF-8). – Gilles 'SO- stop being evil' Oct 24 '10 at 22:07cut -c-8
will select from character 1 to 8. – Sparhawk May 09 '14 at 05:08cut
's equivalent on Windows is? – Pacerier Aug 25 '15 at 13:06command | dd bs=8 count=1 2>/dev/null
. Not saying it's shorter or superior. Just another alternative. – dubiousjim Sep 24 '15 at 03:50cut
,cut -c
works likecut -b
(that is, it doesn't work properly for multi-byte characters). – Stéphane Chazelas Aug 09 '16 at 13:49