# sh disk.sh
use -75%
res 75%
use -75%-1%
res 1%
use -75%-1%-2%
res 2%
use -75%-1%-2%-0%
res 0%
use -75%-1%-2%-0%-1%
res 1%
use -75%-1%-2%-0%-1%-99%
res 99%
final
I am expecting a final result like in the last 'use':
Hi,
the effect you see is caused by the way you feed your loop. The pipe creates a subshell which has its own copies of the variables, the ones in the parent shell are not affected by actions in the subshell.
Process substitution is one way to fix this problem:
df -h | { read REST; while read FS SZ AV US PC MT REST; do useSpPer=${useSpPer}'-'$PC; echo 'use '$useSpPer; echo 'res '$PC; done; echo final $useSpPer; }
use -28%
res 28%
use -28%-28%
res 28%
use -28%-28%-42%
res 42%
use -28%-28%-42%-3%
res 3%
final -28%-28%-42%-3%
Only Bash, Zsh and Ksh93 supports process substitution , which is what the <(...) means. Since you are invoking it with sh , judging by this # sh disk.sh , I suggest you use the command grouping
To explain how this works, this doesn't avoid the subshell problem, as much as put the entire relevant program inside the subshell so nothing loses context.
From the heading you used in post #1 in this thread:
Filesystem Size Used Avail Use% Mounted on
It looks to me like the reads should be changed from:
read REST; while read FS SZ AV US PC MT REST
to:
read REST; while read FS SZ US AV PC REST
where $US will expand to the data in the "Used" field and $PC will expand to the data in the "Use%" (i.e., used percent) field. Note that the standards don't specify the output format used in df -h output (although -h is a common option; it is an extension not required in the standards); on my system the heading used with it is:
Filesystem Size Used Avail Capacity iused ifree %iused Mounted on
where "Capacity" corresponds to the "Use%" heading you listed and in either case "$REST" will expand to the contents of the remaining fields (whether that is just the "Mount on" (directory on which the filesystem is mounted) as on your system, or the "iused" (number of i-nodes used), "ifree" (number of i-nodes free), "%iused" (percentage of i-nodes used), and "Mounted on" (directory on which the filesystem is mounted) fields produced by OS X df -h . If anyone else is trying to use code similar to yours, they need to adapt the arguments passed to read to assign needed fields to variables with names corresponding to the output format produced by df -h , df , or df -P (the last one being the only one with the output format specified by the standards) on their system for fields that they care about.
But, of course, since the code RudiC suggested doesn't use $US or $AV the order in which those are specified in the read command doesn't really matter in the way the script functions; the only thing that is crucial is the number of fields specified before PC (to get the percentage data needed by your script) and having at least one variable listed after PC so the remaining data on each line is not mixed in with the desired data when $PC is expanded.
df -h | {
read REST
while read FS SZ AV US PC MT REST
do useSpPer=${useSpPer}'-'$PC
echo 'use '$useSpPer
echo 'res '$PC
done
echo final $useSpPer
}
there is nothing standardized about the chosen variable names RudiC used. The only thing that matters is that the position in the list of values printed by the command df -h corresponds to the variable names used later in the script. In this specific script with the output produced by dh -h on your system, the following script would produce identical output:
df -h | {
read junk
while read junk junk junk junk needed junk
do useSpPer=${useSpPer}'-'$needed
echo 'use '$useSpPer
echo 'res '$needed
done
echo final $useSpPer
}
If there is a possibility that useSpPer might be an exported variable inherited into the environment of these scripts, it would be safer to define an initial value before the loop as in:
df -h | {
read junk
useSpPer=''
while read junk junk junk junk needed junk
do useSpPer=${useSpPer}'-'$needed
echo 'use '$useSpPer
echo 'res '$needed
done
echo final $useSpPer
}
I used a predefined variable before the loop, thanks everybody, I will try to develop my code of check disk space by sending an email to the admin, if any difficulties, I will get back to you