Portable Way to Get File Size (In Bytes) in the Shell

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



Leave a reply



Submit