Portable way to get file size (in bytes) in the shell
wc -c < filename
(short for word count, -c
prints the byte count) is a portable, POSIX solution. Only the output format might not be uniform across platforms as some spaces may be prepended (which is the case for Solaris).
Do not omit the input redirection. When the file is passed as an argument, the file name is printed after the byte count.
I was worried it wouldn't work for binary files, but it works OK on both Linux and Solaris. You can try it with wc -c < /usr/bin/wc
. Moreover, POSIX utilities are guaranteed to handle binary files, unless specified otherwise explicitly.
get human friendly file size from shell in unix-like environments [portability]
Most implementations of du(1)
accept the -h
flag, which causes it to print the disk usage of the file, or files, specified. The difference between disk usage and file size in normally innocuous, rounding up to the nearest file-system block.
The -h
flag, though widely supported, is an extension. For maximum portability unit conversion would have to be done manually an pointed out by chepner.
*BSD, Illumos, BusyBox, and GNU CoreUtils all support the -h
flag.
Bash - how to list files with size in bytes
If you are looking for statistics about files, then you want to use stat
rather than ls
. eg, with gnu stat:
stat --format=%n:%s *
How can I check the size of a file using Bash?
[ -n file.txt ]
doesn't check its size. It checks that the string file.txt
is non-zero length, so it will always succeed.
If you want to say "size is non-zero", you need [ -s file.txt ]
.
To get a file's size, you can use wc -c
to get the size (file length) in bytes:
file=file.txt
minimumsize=90000
actualsize=$(wc -c <"$file")
if [ $actualsize -ge $minimumsize ]; then
echo size is over $minimumsize bytes
else
echo size is under $minimumsize bytes
fi
In this case, it sounds like that's what you want.
But FYI, if you want to know how much disk space the file is using, you could use du -k
to get the size (disk space used) in kilobytes:
file=file.txt
minimumsize=90
actualsize=$(du -k "$file" | cut -f 1)
if [ $actualsize -ge $minimumsize ]; then
echo size is over $minimumsize kilobytes
else
echo size is under $minimumsize kilobytes
fi
If you need more control over the output format, you can also look at stat
. On Linux, you'd start with something like stat -c '%s' file.txt
, and on BSD and Mac OS X, something like stat -f '%z' file.txt
.
How to find the size of a file and assign it to a variable in Unix
You can use the stat
command which eliminates the need to use AWK.
For example, in Linux with Bash where myfile is your file path:
sz=$(stat -c '%s' myfile)
if [ $sz -eq 100 ]; then
echo "myfile is 100 bytes"
fi
Take note of the equality command -eq
that's the arithmetic binary operator in Bash.
Alternatively, you can use a variable for the file path:
f=my/file/path
sz=$(stat -c '%s' $f)
if [ $sz -eq 100 ]; then
echo "$f is 100 bytes"
fi
efficient way to read the first 128 bytes from a socket but write the rest directly to a file
Maybe using bash
's native TCP socket support? Files like /dev/tcp/HOST/PORT
open sockets to the given host.
Roughly (Untested code due to lack of a test server):
#!/usr/bin/env bash
exec 3<>/dev/tcp/127.0.0.1/61222 # Open a socket on descriptor 3
printf "%s\n" "download|file_dir|file_name" >&3
read -r -N 128 -u 3 signature # Read 128 bytes from descriptor 3
cat <&3 >"$FILE_PATH"
exec 3<&- # Close the socket
How to get file names and file size from tar files using shell script
Your approach is a bit awkward. You only need to capture all filenames to loop over the mandatory files, but you cannot do your check the way you are doing or any additional files in your archive (beyond mandatory files) will cause your test to fail.
A cleaner approach is to use process substitution to feed the size and filename to a loop allowing you to test each of the file sizes (any file less than minimumsize
will cause the archive to fail), while you fill your array of all_names
. You are done with the read loop at that point.
A final loop over all_names
checking if they exist in mandatoryFiles
and incrementing a counter will allow you to check if there was a match against each of the mandatoryFiles
.
One approach would be:
#!/bin/bash
fname="${1:-testData/test_daily.tgz}" ## filename to read
minimumsize=90000 ## min size
mandatoryFiles=(party.dat test1.dat test2.dat) ## mandatory files
declare -a all_names ## all_names array
declare -i mandatory_count=0; ## mandatory count
while read -r size name; do ## read/compare sizes, fill array
all_names+=( "${name##*/}" ); ## store each file name in array w/o path
#condition to check file size is greater than minimum size
if [ "$size" -ge $minimumsize ]; then
echo "$size is over $minimumsize bytes"
else
echo "$size is under $minimumsize bytes"
exit 0
fi
done < <(tar -tzvf "$fname" | awk '{print $3, $6}')
#condition to check all the mandatory files are included in the taz file.
for afile in "${all_names[@]}"; do
if [[ ${mandatoryFiles[@]} =~ "$afile" ]]; then
((mandatory_count++)) ## increment mandatory_count
fi
done
## test if mandatory_count less than number of mandatory files
if [ "$mandatory_count" -lt "${#mandatoryFiles[@]}" ]; then
echo "mandatoryFiles not present - exiting"
exit 1
fi
echo "all files good"
(note: if the file is a .tgz
(g-zipped tar archive), you need to add the 'z'
option as done above)
Look things over and let me know if you have further questions.
Related Topics
How to Filter Data Between 2 Dates with Awk in a Bash Script
Linux Kernel Device Driver to Dma from a Device into User-Space Memory
Remote Linux Server to Remote Linux Server Dir Copy. How
Pass Output as an Argument for Cp in Bash
How to Access an Environment Variable in a .Desktop File's Exec Line
Android Sdk on a 64-Bit Linux MAChine
How to Capture Still Image from Webcam on Linux
Why Can Back-Quotes and $() for Command Substitution Result in Different Output
Can't Run Executable Linked with Libc
Linux Why Can't I Pipe Find Result to Rm
Linux Command Line Howto Accept Pairing for Bluetooth Device Without Pin
How to Remove the Win10's Path from Wsl