I am trying to run an alphabetical sequence in Linux shell. I believe my syntax is correct, but its not giving me each letter, but rather {a..z} all at once. Here is what I have:
COUNTER=0;
for X in {a..z};
do
# Make sure usb is mounted before trying anything
sudo mkdir /media/mounts/sd${X}1
sudo mount /dev/sd${X}1 /media/mounts/sd${X}1
# Find player number from Linux mount point
DATA_DIR=/media/mounts/sd${X}1;
PLAYER_FILE_PATH=`find $DATA_DIR -name "player.*"`;
PLAYER_FILE_ONLY=`basename -- $PLAYER_FILE_PATH`;
PLAYER_NUMBER=`echo "${PLAYER_FILE_ONLY##*.}"`;
# Make sure usb device exists and player number is not empty
if [ -n "$PLAYER_NUMBER" ] && [ $PLAYER_NUMBER -gt 0 ]
then
# Let user know which tracer was found
echo "$PLAYER_NUMBER was found, creating directory to store its .dat files" | tee -a $ERR_LOG_PATH;
echo "${PLAYER_NUMBER}: " >> $LOG_PATH;
let COUNTER ;
# Create directory for player number to dump .dat files and log any errors at output
sudo mkdir $DUMP_DIR/$PLAYER_NUMBER;
NUMBER_DATS=`ls $DATA_DIR/MountsData/*.dat | wc -l`;
DAT_COUNT_ARRAY[$PLAYER_NUMBER]=$NUMBER_DATS
echo "USB $PLAYER_NUMBER has $NUMBER_DATS .dat files";
echo "${NUMBER_DATS}\r\n" >> $LOG_PATH;
cp $DATA_DIR/MountsData/*.dat $DUMP_DIR/$PLAYER_NUMBER 2>> $ERR_LOG_PATH;
# Remove all .dat files directly from usb and log any errors at output
sudo rm $DATA_DIR/MountsData/*.dat 2>> $ERR_LOG_PATH;
fi
done
I get the resulting output:
mount: special device /dev/sd{a..z}1 does not exist
I have tried changing the variable names, capitalization, and referring to them as $X instead of ${X}. I am currently using a Raspberry Pi running Raspbian with a standard Raspbian shell. I ran some test to ensure syntax was right in the terminal and seems like the for loop structure is correct. Am I missing something?
CodePudding user response:
you have to execute it with bash. some os link sh to bash, but some of them link to other shell apps like the dash in ubuntu. to check the linked app in your sh, try to execute this command: file -h /bin/sh
CodePudding user response:
You can write a portable function that will generate the list in a POSIX compatible way. For example to generate a range of ASCII characters from any character (with lower ASCII value) to any ASCII character, you can do:
genasciirange() {
[ -n "$1" -a -n "$2" ] || return 1
local a=$(LC_CTYPE=C printf '%d' "'$1")
local b=$(LC_CTYPE=C printf '%d' "'$2")
[ "$a" -lt "$b" -a "$a" -lt 256 -a "$b" -lt 256 ] || return 1
local c="$a"
while [ "$c" -le "$b" ]; do
printf " \\$(printf 'o' "$c")"
c=$((c 1))
done
printf "\n"
}
(where -a is the older AND for conditions within [...], you can replace with [...] && [...] if you desire)
The conversion from character to ASCII value is handled by LC_CTYPE=C printf '%d' "'$somechar" and from ASCII value to character by converting to octal value and then outputting the escaped octal code, e.g. printf " \\$(printf 'o' "$someasciival")"
Example Use/Output
genasciirange a z
a b c d e f g h i j k l m n o p q r s t u v w x y z
or for example:
genasciirange Q q
Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q
In your case, you can include the function and replace the brace-expansion with:
for X in $(genasciirange a z)
Using the jot Utility
A fairly common utility available is jot. It is simply an advanced seq that can generate sequential or random data. For example, for a-z you could do:
jot -s " " -w %c 26 a
a b c d e f g h i j k l m n o p q r s t u v w x y z
It is likely available for your Linux distribution already. If not, you can build from source athena-jot-9.0.orig.tar.gz from Ubuntu Source Package: athena-jot (9.0-7)
awk can be used as well.
Look things over and let me know if you have questions.
