Using variable as a file name

Ok, I will admit right up front that this is stupid, and I shouldn't be hung up on this. I have a script that checks the unallocated areas of space, and checks to see if they are empty or not. If they aren't empty, I run xxd to allow for more analysis.

I have commented out the rest of the script for now. The following section checks if they are empty, and either disregards or creates the output file.

sum ./$iname/Unallocated*.raw | while read line
	do
		if [ `echo $line | awk '{print $1}'` = 00000 ]
			then
				echo $line | awk '{print $3 " is empty, disregarding."}'

			else
				echo $line | awk '{print $3 " is not empty.  Creating XXD report"}'
				ofname=`echo $line | awk '{print $3}'`				
				echo "xxd -a > ${ofname}.txt"
		fi
	done

No matter what I do, I can not get it to create the output files using the ofname variable. If I do echo $ofname, it shows correctly, but when I put it the xxd command, it's blank. Using echo to echo the xxd command back shows the filename as there.

echo "xxd -a > $ofname.txt"

I don't see where xxd runs. How about:

xxd -a > $ofname.txt

As I said in the text, I was using echo to echo back the xxd command as it should be ran. This echos back the command just fine, file name and all. When I actually run xxd (not echo'ed), it doesn't have the file name. Usinb bash -xv, it shows the command as being 'xxd -a', with no file name attached at all.

I have tried putting the variable in (), {}, and any other crazy idea I had, and still nothing.

Any chance the output file name has embedded blanks or other special characters that are confusing bash? In other words, what are typical examples of what $ofname translates to?

I thought of that. But no.

The file names are generated by the script in the form of Unallocated-[start sector]-[end sector].raw, where denotes a variable. These files are created as expected.

Full script (keep in mind most of it is commented out) :

#!/bin/bash -xv

image="$1"

#Create a non-spaced, non-extensioned version of the filename for a folder name.
x="$image"
y=${x%%.*}
iname=`echo ${y##*/} | sed 's/ /_/g'`

#Determine if a folder with the same name as the image file exists, if not create.
#if [ -d $iname || -d Reports ]
#	then	
#		read  -a c -p"$iname or Reports folder(s) exists, continuing may overwrite previous data.  Continue? (y/n)"
#		if [ $c = n ]
#			then
#				exit 1
#		fi
#	else
#		echo "folder does not exist, creating"
#		mkdir $iname Reports
#fi
#
#Run MMLS to find empty portions of the disk, and find entries with 'Unallocated' in them.
#mmls "$image" | grep Unallocated | while read line
#	do
#		ssect=`echo $line | awk '{print $3+0}'`
#		esect=`echo $line | awk '{print $4+0}'`
#		bleng=`echo $line | awk '{print $5*512}'`
#		fname=`echo $line | awk '{print "Unallocated-'${ssect}'-'${esect}'"}'`
#		ewfexport -f raw -S 0 -o $ssect -B $bleng -t ./$iname/$fname "$image"
#	done
#
#Determine if a file is empty or contains data.
#echo "Results of sum command against all generated raw files" > $iname-sumresults.txt
#sum ./$iname/Unallocated*.raw >> $iname-sumresults.txt
sum ./$iname/Unallocated*.raw | while read line
	do
		if [ `echo $line | awk '{print $1}'` = 00000 ]
			then
				echo $line | awk '{print $3 " is empty, disregarding."}'

			else
				echo $line | awk '{print $3 " is not empty.  Creating XXD report"}'
				ofname=`echo $line | awk '{print $3}'`				
				`xxd -a > "$ofname".txt`
		fi
	done

I can't find the problem. Sorry.

I would try making some other intermediate variables, to better follow what is happening and track down where the glitch is.

For example, I might change the following:

if [ `echo $line | awk '{print $1}'` = 00000 ]

to something like (with better name than "var_x":

var_x=`echo $line | awk '{print $1}'`
echo var_x = $var_x >> logfile
if [ "$var_x" = "00000" ]

Why is the xxd command in back-ticks, since results not assigned to anything? Just wondering.

`xxd -a > "$ofname".txt`

Well, at least I feel a little better that my problem wasn't glaringly obvious. But then I feel bad again because I still don't know what the hell is going on.

Sometimes I put those around stand alone commands. Weird habit I picked up that I'm trying to break.

Not merely odd but actively bad, since any output can cause the shell to spit a syntax error. Worst case, if the command outputs a valid program name, it may be run.

Point taken.

Regardless, that isn't the cause of my current problems. I removed them, and it's still acting the same.

Have you echoed the variables to see if they are what you think? Put quotes around them to see if spaces or nonprinting characters have fouled it up somehow.

echo "x is '$x'"

Why don't you post an execution log (xtrace on) so we can see what's happening?

And, BTW, why do you read line and then awk the relevant fields instead of read DISK STH PART REST and then use those variables? Then you will know if the output file name is empty or not.

Forgive my lack of knowledge, but I know nothing of xtrace. The searches I've done on it since reading your message didn't shed any additional light on it. More information would be welcome.

I mean, using echos of the variables at various places shows that those are performing as expected. Using bash -xv shows that everything is performing as expected, except this one command. I can't figure it out.

I used while read line because I know that. I have never heard of read DISK STH PART REST. What does that do?

I think the syntax is wrong, isn't this the correct syntax, assuming you want to take hex dump of $ofname and redirect o/p to another text file ${ofname}.txt ?

xxd -a "$ofname" > "${ofname}.txt"

bash -xv is exactly what I was talking of. Post an execution log with vx set.

read A B C D reads a line from stdin, splits it at occurrences of IFS, and assigns the first word to variable A, the second to var. B, and so on. The last variable, in this case D, will contain its positional word plus the rest of the line, should more words exist.
The names I mentioned above were sheer assumptions - DISK will contain what you extract with awk $1, PART will be $3, on so on.
Your code snippet would become sth like

read DISK STH PART REST
[ "$DISK" -eq "00000" ] && printf "%s", "$PART is empty" || { printf "%s", "$PART is not empty"; xxd -a > ${PART}.txt

Here is the output of bash -xv :

#!/bin/bash -xv

image="$1"
+ image='AD-ACE Recert.E01'

#Create a non-spaced, non-extensioned version of the filename for a folder name.
x="$image"
+ x='AD-ACE Recert.E01'
y=${x%%.*}
+ y='AD-ACE Recert'
iname=`echo ${y} | sed 's/ /_/g'`
echo ${y} | sed 's/ /_/g'
++ echo AD-ACE Recert
++ sed 's/ /_/g'
+ iname=AD-ACE_Recert

#Determine if a folder with the same name as the image file exists, if not create.
if [ -d $iname ]
	then	
		read  -a c -p"$iname folder(s) exists, continuing may overwrite previous data.  Continue? (y/n)"
		if [ $c = n ]
			then
				exit 1
		fi
	else
		echo "folder does not exist, creating"
		mkdir $iname
fi
+ '[' -d AD-ACE_Recert ']'
+ echo 'folder does not exist, creating'
+ mkdir AD-ACE_Recert

#Run MMLS to find empty portions of the disk, and find entries with 'Unallocated' in them.
mmls "$image" | grep Unallocated | while read line
	do
		ssect=`echo $line | awk '{print $3+0}'`
		esect=`echo $line | awk '{print $4+0}'`
		bleng=`echo $line | awk '{print $5*512}'`
		fname=`echo $line | awk '{print "Unallocated-'${ssect}'-'${esect}'"}'`
		ewfexport -f raw -S 0 -o $ssect -B $bleng -t ./$iname/$fname "$image" 2> /dev/null
	done
+ mmls 'AD-ACE Recert.E01'
+ grep Unallocated
+ read line
echo $line | awk '{print $3+0}'
++ echo 01: ----- 0000000000 0000000127 0000000128 Unallocated
++ awk '{print $3+0}'
+ ssect=0
echo $line | awk '{print $4+0}'
++ echo 01: ----- 0000000000 0000000127 0000000128 Unallocated
++ awk '{print $4+0}'
+ esect=127
echo $line | awk '{print $5*512}'
++ echo 01: ----- 0000000000 0000000127 0000000128 Unallocated
++ awk '{print $5*512}'
+ bleng=65536
echo $line | awk '{print "Unallocated-'${ssect}'-'${esect}'"}'
++ echo 01: ----- 0000000000 0000000127 0000000128 Unallocated
++ awk '{print "Unallocated-0-127"}'
+ fname=Unallocated-0-127
+ ewfexport -f raw -S 0 -o 0 -B 65536 -t ./AD-ACE_Recert/Unallocated-0-127 'AD-ACE Recert.E01'
+ read line
echo $line | awk '{print $3+0}'
++ echo 05: ----- 0000497792 0000501758 0000003967 Unallocated
++ awk '{print $3+0}'
+ ssect=497792
echo $line | awk '{print $4+0}'
++ echo 05: ----- 0000497792 0000501758 0000003967 Unallocated
++ awk '{print $4+0}'
+ esect=501758
echo $line | awk '{print $5*512}'
++ echo 05: ----- 0000497792 0000501758 0000003967 Unallocated
++ awk '{print $5*512}'
+ bleng=2031104
echo $line | awk '{print "Unallocated-'${ssect}'-'${esect}'"}'
++ echo 05: ----- 0000497792 0000501758 0000003967 Unallocated
++ awk '{print "Unallocated-497792-501758"}'
+ fname=Unallocated-497792-501758
+ ewfexport -f raw -S 0 -o 497792 -B 2031104 -t ./AD-ACE_Recert/Unallocated-497792-501758 'AD-ACE Recert.E01'
+ read line

#Determine if a file is empty or contains data.
echo "Results of sum command against all generated raw files" > $iname-sumresults.txt
+ echo 'Results of sum command against all generated raw files'
sum ./$iname/Unallocated*.raw >> $iname-sumresults.txt
+ sum ./AD-ACE_Recert/Unallocated-0-127.raw ./AD-ACE_Recert/Unallocated-497792-501758.raw
sum ./$iname/Unallocated*.raw | while read line
	do
		if [ `echo $line | awk '{print $1}'` = 00000 ]
			then
				echo $line | awk '{print $3 " is empty, disregarding."}'

			else
				echo $line | awk '{print $3 " is not empty.  Creating XXD report"}'
				opxxd=`echo $line | awk '{print $3}'`		
				xxd -a > $opxxd.txt
		fi
	done
+ sum ./AD-ACE_Recert/Unallocated-0-127.raw ./AD-ACE_Recert/Unallocated-497792-501758.raw
+ read line
echo $line | awk '{print $1}'
++ echo 16715 64 ./AD-ACE_Recert/Unallocated-0-127.raw
++ awk '{print $1}'
+ '[' 16715 = 00000 ']'
+ echo 16715 64 ./AD-ACE_Recert/Unallocated-0-127.raw
+ awk '{print $3 " is not empty.  Creating XXD report"}'
echo $line | awk '{print $3}'
++ echo 16715 64 ./AD-ACE_Recert/Unallocated-0-127.raw
++ awk '{print $3}'
+ opxxd=./AD-ACE_Recert/Unallocated-0-127.raw
+ xxd -a
+ read line

Thanks for the extra info. That will make my code a little leaner, if I ever get this script working...

Having reproduced that xxd code line here on my system, I think that Yoda in post#14 is right: xxd has no file to operate on, reads stdin, gets an immediate end-of-file condition, and exits. It should have created a 0 byte output file, though. Can you check?

Well, that is embarrassing. I have no idea why I didn't see that before.

Thank you RudiC and Yoda.