Convert decimal to hexadecimal in UNIX shell script
In a UNIX shell script, what can I use to convert decimal numbers into hexadecimal? I thought od would do the trick, but it’s not realizing I’m feeding it ASCII representations of numbers. printf? Gross! Using it for now, but what else is available?
I have to ask, what’s gross about printf? Many common programming languages support printf-like formatting, so the printf solutions below would surely be the easiest for developers to understand.
Boy, I don’t know — that was five years ago! I think maybe I thought it wasn’t true shell or something.
13 Answers 13
There are probably ways of doing that with builtin functions in all shells but it would be less portable. I’ve not checked the POSIX sh specs to see whether it has such capabilities.
printf isn’t aribtrary precision. bc is. for example, taking 238862874857408875879219909679752457540 as input, printf gives us «Result too large». the BC method works great for things larger than a standard int/long/bigint
If you want to filter a whole file of integers, one per line:
( echo "obase=16" ; cat file_of_integers ) | bc
@skiphoppy: If you write: echo «obase=16; 12 34 56» | bc you get 1E240, just the same as if you wrote: echo «obase=16; 123456» | bc. So the way to deal with arbitrary numbers of integers all on one line is to put each number on its own line: tr ‘ ‘ ‘\015’
@Bill Karwin, or zsh, or busybox, but maybe not some shell I haven’t tried? I don’t keep plain sh installed anymore but clearly skiphoppy is looking for what other options there are
@Sridhar-Sarnobat, this is decimal to hexadecimal. I assume you mean convert hex to dec. To do that, set ibase=16 . You might like to read the manual on bc for more details.
you would like to add that bc is case sensitive. meaning echo «ibase=16; dead» | bc will not work, you need to do echo «ibase=16; DEAD» | bc , I was bit surprised by this
Hexidecimal to decimal:
$ echo $((0xfee10000)) 4276158464
Decimal to hexadecimal:
bash-4.2$ printf '%x\n' 4294967295 ffffffff bash-4.2$ printf -v hex '%x' 4294967295 bash-4.2$ echo $hex ffffffff
-v VAR is a bash extension. Not mentioned in the man page, revealed only if one calls printf without arguments
#!/bin/bash : declare -r HEX_DIGITS="0123456789ABCDEF" dec_value=$1 hex_value="" until [ $dec_value == 0 ]; do rem_value=$((dec_value % 16)) dec_value=$((dec_value / 16)) hex_digit=$ hex_value="$$" done echo -e "$"
@SasQ using brackets forces interpretation of the symbol that you intended to be used, i.e. just MY_NUMBER. Using brackets allows you to do things like $> to concatenate variable names.
In my case, I stumbled upon one issue with using printf solution:
$ printf «%x» 008 bash: printf: 008: invalid octal number
The easiest way was to use solution with bc, suggested in post higher:
@Matthieu It mentions the issue of numbers with leading zeros, which Bash printf unhelpfully interprets as octal, and demonstrates a solution that avoids the problem.
In zsh you can do this sort of thing:
% typeset -i 16 y % print $(( [#8] x = 32, y = 32 )) 8#40 % print $x $y 8#40 16#20 % setopt c_bases % print $y 0x20
I believe Bash has similar capabilities.
xd() < printf "hex>" while read i do printf "dec $(( 0x$ ))\n\nhex> " done > dx() < printf "dec>" while read i do printf 'hex %x\n\ndec> ' $i done >
# number conversion. while `test $ans='y'` do echo "Menu" echo "1.Decimal to Hexadecimal" echo "2.Decimal to Octal" echo "3.Hexadecimal to Binary" echo "4.Octal to Binary" echo "5.Hexadecimal to Octal" echo "6.Octal to Hexadecimal" echo "7.Exit" read choice case $choice in 1) echo "Enter the decimal no." read n hex=`echo "ibase=10;obase=16;$n"|bc` echo "The hexadecimal no. is $hex" ;; 2) echo "Enter the decimal no." read n oct=`echo "ibase=10;obase=8;$n"|bc` echo "The octal no. is $oct" ;; 3) echo "Enter the hexadecimal no." read n binary=`echo "ibase=16;obase=2;$n"|bc` echo "The binary no. is $binary" ;; 4) echo "Enter the octal no." read n binary=`echo "ibase=8;obase=2;$n"|bc` echo "The binary no. is $binary" ;; 5) echo "Enter the hexadecimal no." read n oct=`echo "ibase=16;obase=8;$n"|bc` echo "The octal no. is $oct" ;; 6) echo "Enter the octal no." read n hex=`echo "ibase=8;obase=16;$n"|bc` echo "The hexadecimal no. is $hex" ;; 7) exit ;; *) echo "invalid no." ;; esac done
Convert decimal to hex in Bash?
A quicky for my archives: convert decimal to hex in Bash, and convert hexadecimal to decimal, in Bash. In mathematics and computing, hexadecimal (also base 16, or hex) is a positional numeral system with a radix, or base, of 16. It uses sixteen distinct symbols, most often the symbols 0-9 to represent values zero to nine, and A, B, C, D, E, F (or alternatively a-f) to represent values ten to fifteen. If you want to convert hexadecimal values to decimal and decimal values to hexadecimal, here’s how. All on the bash prompt…
You can use your Linux Bash shell to easily convert decimal values to hexadecimal, and vice versa. For example:
Decimal to hexadecimal in bash
Convert decimal to hexadecimal in Bash:
printf '%x\n' 26560 67c0
Code language: Bash (bash)
Convert hexadecimal to decimal in Bash:
echo $((0x000067c0)) 26560
Code language: Bash (bash)
echo $((0x67c0)) 26560
Code language: Bash (bash)
printf '%d\n' 0x67c0 26560
Code language: Bash (bash)
Convert Unix timestamps to dates in Bash
How to convert Unix timestamps to dates in Bash is a little irrelevant in a post on converting decimal to hex in Bash, but it’s still converting something in Bash 🙂 .
Suppose you have an Unix timestamp that you want to convert to a date, here is how with two one liners:
date -d @timestamp
Code language: Bash (bash)
date -d @($date -u +timestamp)
Code language: Bash (bash)
And vice versa, convert a date to an Unix timestamp:
date -d '04/05/2017 11:13:00' +"%s"
Code language: Bash (bash)
The date string is too complex to be documented in the man page, so it is described in info: info ‘(coreutils) date invocation’ .
Related Posts
- MySQL InnoDB performance improvement: InnoDB buffer pool… MySQL
- Windows 11/10 and WSL 2 DevOps environment Windows Server
- Tunnel RDP through SSH & PuTTY Windows Server
- Grep for forensic log parsing and analysis on Windows Server… Web application security
- Installing Debian GNU/Linux 7.0 (Wheezy) on HP EliteBook… GNU Linux
- Redirect HTTP to HTTPS Windows Server
hongkongkiwi / dec_to_hex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
#! /bin/bash -ue |
# # |
# Simple shell script to convert decimal to hex |
# Created by hongkongkiwi: https://gist.github.com/hongkongkiwi/02d8bcde0c810f8dff6b6a96d11ce6bd |
# Usage: |
# ./dec_hex «12356» |
# ./dec_hex -n «12356» |
# ./dec_hex -n -l «12356» |
# ./dec_hex -n -l -o «12356» |
# # |
HELP= » $0 [-n|—no-leading] [-o|—hex-only] [-l|—lowercase] « |
NO_LEADING= » « |
HEX_ONLY= » « |
LOWERCASE= » « |
for ARG in $@ ; do |
case » $ARG » in |
‘ -n ‘ | ‘ —no-leading ‘ ) NO_LEADING= » yes » ;; |
‘ -o ‘ | ‘ —hex-only ‘ ) HEX_ONLY= » yes » ;; |
‘ -l ‘ | ‘ —lowercase ‘ ) LOWERCASE= » yes » ;; |
‘ -h ‘ | ‘ —help ‘ ) echo >&2 » $HELP » ; exit 255;; |
esac |
# Number is always last arg |
NUM= » $ARG « |
done |
if ! [[ » $NUM » =~ ^8+$ ]] ; then |
echo >&2 » ERROR: pass a decimal integer » ; echo >&2 » $HELP » ; exit 255 ; |
fi |
if [ -n » $NO_LEADING » ] ; then |
# Strip off leading zeros as printf does not like it |
NUM= » $( echo » $NUM » | sed ‘ s|^[0]*||g ‘ ) « |
OUTPUT= » $( printf » %x\n » » $NUM » ) « |
else |
# Strip everything but leading zeros |
LEADING= » $( echo » $NUM » | sed -n ‘ s/^\([0]*\)5\+/\1/p ‘ ) « |
# Strip off leading zeros as printf does not like it |
NUM= » $( echo » $NUM » | sed ‘ s|^[0]*||g ‘ ) « |
OUTPUT= » $( printf » $ %x\n » » $NUM » ) « |
fi |
if [ -n » $LOWERCASE » ] ; then |
OUTPUT= » $( echo » $OUTPUT » | tr ‘ [:upper:] ‘ ‘ [:lower:] ‘ ) « |
else |
OUTPUT= » $( echo » $OUTPUT » | tr ‘ [:lower:] ‘ ‘ [:upper:] ‘ ) « |
fi |
if [ -n » $HEX_ONLY » ] ; then |
echo » $OUTPUT « |
else |
echo » 0x $OUTPUT « |
fi |
exit 0 |
BASH base conversion from decimal to hex
In Bash, how does one do base conversion from decimal to another base, especially hex. It seems easy to go the other way:
With a web-search, I found a script that does the maths and character manipulation to do the conversion, and I could use that as a function, but I’d have thought that bash would already have a built-in base conversion — does it?
4 Answers 4
With bash (or any shell, provided the printf command is available (a standard POSIX command often built in the shells)):
With zsh , you can also do:
That works for bases from 2 to 36 (with 0-9a-z case insensitive as the digits).
$(([#16]dev)) (with only one # ) expands to 16#55 or 0x55 (as a special case for base 16) if the cbases option is enabled (also applies to base 8 ( 0125 instead of 8#125 ) if the octalzeroes option is also enabled).
Which works for bases from 2 to 64 (with 0-9a-zA-Z@_ as the digits).
With ksh and zsh , there’s also:
$ typeset -i34 x=123; echo "$x" 34#3l
Though that’s limited to bases up to 36 in ksh88, zsh and pdksh and 64 in ksh93.
Note that all those are limited to the size of the long integers on your system ( int ‘s with some shells). For anything bigger, you can use bc or dc .
$ echo 'obase=16; 9999999999999999999999' | bc 21E19E0C9BAB23FFFFF $ echo '16o 9999999999999999999999 p' | dc 21E19E0C9BAB23FFFFF
With supported bases ranging from 2 to some number required by POSIX to be at least as high as 99. For bases greater than 16, digits greater than 9 are represented as space-separated 0-padded decimal numbers.
$ echo 'obase=30; 123456' | bc 04 17 05 06
Or same with dc ( bc used to be (and still is on some systems) a wrapper around dc ):
$ echo 30o123456p | dc 04 17 05 06
@flarn2006. With bash builtins, you can input numbers in any base, but not output in any base other than 8, 10 and 16. For other bases, you’d need another shell like zsh or ksh or use bc/dc .
@StéphaneChazelas Really? That’s kind of weird. It almost seems like they were too lazy to program in a syntax for it or something; there’s no way the idea of outputting in any base didn’t cross their minds if they implemented inputting.
$ printf "%d %x\n" $((16#55)) $((10#85)) 85 55
To assign the value to a variable use command substitution:
$ x=$( printf "%x" 85 ) ; echo $x 55
-v would avoid the fork and pipe (in bash, not ksh93 which wouldn’t fork here as printf is builtin). Note that $((16#55)) is not standard either.
Use the built-in Arithmetic Expansion substitution present in all POSIX compliant shells — which is pretty much universal these days.
$ hex=dead $ dec=$((0x$hex)) $ echo $dec 57005
CAUTION: Particularly in the last example the expansion could cause unexpected results — the hex digits in the variable ‘hex’ have to form a legal hex constant, otherwise potentially obscure error messages happen. e.g. if ‘hex’ were ‘0xdead’, the arithmetic expansion would become 0x0xdead, which is not interpretable as a constant. Of course, in that case the arithmetic expansion $(($hex)) would do the trick. It is left as an exercise for the reader to create the simple substring processing pattern matching that would remove an optional ‘0x’ prefix.