I am working on ARM-based modem Linux host machine and I need to read a bin file as an 8-,16- or 32- bits array. I basically need to encrypt the file in question and was thinking of just XOR-ing the bits with a random bit sequence (I don't need a very complex system). The Linux host doesn't have C or PERL modules in it so I cannot use them and hence I need to do it using a shell script. Can anyone give me some pointers on how to proceed with this?
Bash – Reading a binary file as an array of bytes or 16 or 32 bits using shell script
bashlinuxshellshell-script
Related Solutions
If on Linux (with the util-linux
utilities including getopt
installed, or the one from busybox
), you can do:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]='var1()' # opt with argument, array variable
[opt2:]='var2()' # ditto
[opt3:]='var3' # opt with argument, scalar variable
[opt4]='var4' # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "${!opt_spec[*]}" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=${o#--}
if ((${opt_spec[$o]+1})); then # opt without argument
eval "${opt_spec[$o]}=true"
else
o=$o:
case "${opt_spec[$o]}" in
(*'()') eval "${opt_spec[$o]%??}+=(\"\$1\")";;
(*) eval "${opt_spec[$o]}=\$1"
esac
shift
fi
esac
done
echo "var1: ${var1[@]}"
That way, you can call your script as:
my-script --opt1=foo --opt2 bar --opt4 -- whatever
And getopt will do the hard work of parsing it, handling --
and abbreviations for you.
Alternatively, you could rely on the type of the variable instead of specifying it in your $opt_spec
associative array definition:
declare -A opt_spec
var1=() var2=() var4=false
unset var3
opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
parsed_opts=$(
IFS=,
getopt -o + -l "${!opt_spec[*]}" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=${o#--}
if ((${opt_spec[$o]+1})); then # opt without argument
eval "${opt_spec[$o]}=true"
else
o=$o:
case $(declare -p "${opt_spec[$o]}" 2> /dev/null) in
("declare -a"*) eval "${opt_spec[$o]}+=(\"\$1\")";;
(*) eval "${opt_spec[$o]}=\$1"
esac
shift
fi
esac
done
echo "var1: ${var1[@]}"
You can add short options like:
declare -A long_opt_spec short_opt_spec
var1=() var2=() var4=false
unset var3
long_opt_spec=(
[opt1:]=var1 # opt with argument
[opt2:]=var2 # ditto
[opt3:]=var3 # ditto
[opt4]=var4 # boolean opt without argument
)
short_opt_spec=(
[a:]=var1
[b:]=var2
[c]=var3
[d]=var4
)
parsed_opts=$(
IFS=; short_opts="${!short_opt_spec[*]}"
IFS=,
getopt -o "+$short_opts" -l "${!long_opt_spec[*]}" -- "$@"
) || exit
eval "set -- $parsed_opts"
while [ "$#" -gt 0 ]; do
o=$1; shift
case $o in
(--) break;;
(--*)
o=${o#--}
if ((${long_opt_spec[$o]+1})); then # opt without argument
eval "${long_opt_spec[$o]}=true"
else
o=$o:
case $(declare -p "${long_opt_spec[$o]}" 2> /dev/null) in
("declare -a"*) eval "${long_opt_spec[$o]}+=(\"\$1\")";;
(*) eval "${long_opt_spec[$o]}=\$1"
esac
shift
fi;;
(-*)
o=${o#-}
if ((${short_opt_spec[$o]+1})); then # opt without argument
eval "${short_opt_spec[$o]}=true"
else
o=$o:
case $(declare -p "${short_opt_spec[$o]}" 2> /dev/null) in
("declare -a"*) eval "${short_opt_spec[$o]}+=(\"\$1\")";;
(*) eval "${short_opt_spec[$o]}=\$1"
esac
shift
fi
esac
done
echo "var1: ${var1[@]}"
You can do this using List of array keys. From the bash
man page:
${!name[@]}
${!name[*]}
List of array keys. If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to
0
if name is set and null otherwise. When@
is used and the expansion appears within double quotes, each key expands to a separate word.
For your example:
#!/bin/bash
AR=('foo' 'bar' 'baz' 'bat')
for i in "${!AR[@]}"; do
printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done
This results in:
${AR[0]}=foo
${AR[1]}=bar
${AR[2]}=baz
${AR[3]}=bat
Note that this also work for non-successive indexes:
#!/bin/bash
AR=([3]='foo' [5]='bar' [25]='baz' [7]='bat')
for i in "${!AR[@]}"; do
printf '${AR[%s]}=%s\n' "$i" "${AR[i]}"
done
This results in:
${AR[3]}=foo
${AR[5]}=bar
${AR[7]}=bat
${AR[25]}=baz
Best Answer
Use
tr
(here rot128):For XOR 123, you'd need to compute the corresponding
tr
line:More generally, to answer the question, to convert a file into an array of numbers to be used by the shell with standard commands:
You can then apply the transformations you want and convert back to a file with
awk
'sprintf("%c")
.That's going to be very inefficient though.
Like:
You can use
od -An -vtu2
, to get 16bit numbers, but note that it is in the local endianness, so when converting back to characters, you have to take that into account.