I've got a script that checks for 0-size, but I thought there must be an easier way to check for file sizes instead. I.e. file.txt
is normally 100k; how to make a script check if it is less than 90k (including 0), and make it do wget a new copy because the file is corrupt in this case.
What I'm currently using..
if [ -n file.txt ]
then
echo "everything is good"
else
mail -s "file.txt size is zero, please fix. " [email protected] < /dev/null
# Grab wget as a fallback
wget -c https://www.server.org/file.txt -P /root/tmp --output-document=/root/tmp/file.txt
mv -f /root/tmp/file.txt /var/www/file.txt
fi
This question is related to
bash
For getting the file size in both Linux and Mac OS X (and presumably other BSDs), there are not many options, and most of the ones suggested here will only work on one system.
Given f=/path/to/your/file
,
what does work in both Linux and Mac's Bash:
size=$( perl -e 'print -s shift' "$f" )
or
size=$( wc -c "$f" | awk '{print $1}' )
The other answers work fine in Linux, but not in Mac:
du
doesn't have a -b
option in Mac, and the BLOCKSIZE=1 trick doesn't work ("minimum blocksize is 512", which leads to a wrong result)
cut -d' ' -f1
doesn't work because on Mac, the number may be right-aligned, padded with spaces in front.
So if you need something flexible, it's either perl
's -s
operator , or wc -c
piped to awk '{print $1}'
(awk will ignore the leading white space).
And of course, regarding the rest of your original question, use the -lt
(or -gt
) operator :
if [ $size -lt $your_wanted_size ]; then
etc.
I would use du
's --threshold
for this. Not sure if this option is available in all versions of du
but it is implemented in GNU's version.
Quoting from du(1)'s manual:
-t, --threshold=SIZE
exclude entries smaller than SIZE if positive, or entries greater
than SIZE if negative
Here's my solution, using du --threshold=
for OP's use case:
THRESHOLD=90k
if [[ -z "$(du --threshold=${THRESHOLD} file.txt)" ]]; then
mail -s "file.txt size is below ${THRESHOLD}, please fix. " [email protected] < /dev/null
mv -f /root/tmp/file.txt /var/www/file.txt
fi
The advantage of that, is that du
can accept an argument to that option in a known format - either human as in 10K
, 10MiB
or what ever you feel comfortable with - you don't need to manually convert between formats / units since du
handles that.
For reference, here's the explanation on this SIZE
argument from the man page:
The SIZE argument is an integer and optional unit (example: 10K is
10*1024). Units are K,M,G,T,P,E,Z,Y (powers of 1024) or KB,MB,... (powers
of 1000). Binary prefixes can be used, too: KiB=K, MiB=M, and so on.
This works in both linux and macos
function filesize
{
local file=$1
size=`stat -c%s $file 2>/dev/null` # linux
if [ $? -eq 0 ]
then
echo $size
return 0
fi
eval $(stat -s $file) # macos
if [ $? -eq 0 ]
then
echo $st_size
return 0
fi
return -1
}
stat appears to do this with the fewest system calls:
$ set debian-live-8.2.0-amd64-xfce-desktop.iso
$ strace stat --format %s $1 | wc
282 2795 27364
$ strace wc --bytes $1 | wc
307 3063 29091
$ strace du --bytes $1 | wc
437 4376 41955
$ strace find $1 -printf %s | wc
604 6061 64793
It surprises me that no one mentioned stat
to check file size. Some methods are definitely better: using -s
to find out whether the file is empty or not is easier than anything else if that's all you want. And if you want to find files of a size, then find
is certainly the way to go.
I also like du
a lot to get file size in kb, but, for bytes, I'd use stat
:
size=$(stat -f%z $filename) # BSD stat
size=$(stat -c%s $filename) # GNU stat?
alternative solution with awk and double parenthesis:
FILENAME=file.txt
SIZE=$(du -sb $FILENAME | awk '{ print $1 }')
if ((SIZE<90000)) ; then
echo "less";
else
echo "not less";
fi
Based on gniourf_gniourf’s answer,
find "file.txt" -size -90k
will write file.txt
to stdout if and only if the size of file.txt
is less than 90K, and
find "file.txt" -size -90k -exec command \;
will execute the command command
if file.txt
has a size less than 90K.
I have tested this on Linux.
From find(1)
,
… Command-line arguments following (the
-H
,-L
and-P
options) are taken to be names of files or directories to be examined, up to the first argument that begins with ‘-’, …
(emphasis added).
python -c 'import os; print (os.path.getsize("... filename ..."))'
portable, all flavours of python, avoids variation in stat dialects
If your find
handles this syntax, you can use it:
find -maxdepth 1 -name "file.txt" -size -90k
This will output file.txt
to stdout if and only if the size of file.txt
is less than 90k. To execute a script script
if file.txt
has a size less than 90k:
find -maxdepth 1 -name "file.txt" -size -90k -exec script \;
Okay, if you're on a Mac, do this:
stat -f %z "/Users/Example/config.log"
That's it!
If you are looking for just the size of a file:
$ cat $file | wc -c
> 203233
ls -l $file | awk '{print $6}'
assuming that ls command reports filesize at column #6
Source: Stackoverflow.com