简体   繁体   中英

Unix Bash Shell Scripting File Size

I am working on a bash shell script which requires me to display files in order of size in a given directory. If the size of a file is 0, I am to ask the user if they would like to delete it. So far I have this:

#!/bin/bash
FILE=$(ls -S $1)
for FIL in ${FILE}
do
    echo ${FIL}
done

This displays the files in order of size, but I am unsure how to prompt the user to erase the files with a size of 0.

Thanks for your help!

So if we want to stay as close as possible to your current approach, we could do it like this:

#!/bin/bash
FILE="$(ls -S "$1")"

for f in $FILE
do
    file_size_bytes=$(du "$f" | cut -f1)
    echo "$f"

    if [[ "$file_size_bytes" -eq 0 ]]
    then
        read -r -p "Would you like to delete the zero-byte file ${f}? [Y/n]: " input

        if [[ "$input" = [Yy] ]]
        then
            rm "$f"
        fi
    fi
done

Another answer used stat , but stat isn't POSIX or portable, but if you're only running under Linux, stat is a good approach.

In the above example, read -p is used to prompt the user for input, and store the result in $input . We use [[ "$input" = [Yy] ]] to see if the input is either Y or y .

The way it's currently written, you have to type y or Y and press enter to delete the file. If you want it to happen as soon as the user hits y or Y , add -n 1 to read to make it only read one character.

You also don't need to use ${var} unless you're putting it inside another string, or if you need to use some kind of parameter expansion.

As a side note, this sounds like it's some type of homework or learning experience, so, please look up every command, option, and syntax element in the above and really learn how it works.

find /your/path/ -size 0 -exec echo rm -i {} \; # will fail if there are spaces in any file names

better way:

find /your/path/ -size 0 -print0 | xargs -0 rm -i

Remove the echo to delete the files

Thanks @Will, @AdamKatz.

You can make use of redirection and redirect stdin to another file descriptor while feeding the loop with process substitution to accomplish your goal. eg:

#!/bin/bash

[ -z "$1" ] && {
    printf "error: insufficient input, usage: %s <path>\n" "${0//*\/}"
    exit 0;
}

exec 3<&0   # temprorary redirection of stdin to fd 3

while read -r line; do
    printf " rm '%s' ? " "$line"
    read -u 3 ans   # read answer for fd 3
    anslower="${ans,,}"
    if [ "${anslower:0:1}" = "y" ]; then
        printf " %s  =>  removed.\n" "$line"
        # rm "$line"
    else
        printf " %s  =>  unchanged.\n" "$line"
    fi
done < <(find "$1" -type f -size 0)

exec 3<&-   # close temporary redirection

note: the actual rm command is commented out to insure you don't remove wanted files by accident until your testing is complete.

Example Use/Output

$ bash findzerosz.sh ../tmp/stack/dat/tmp/tst/tdir
 rm '../tmp/stack/dat/tmp/tst/tdir/file4.html' ? n
 ../tmp/stack/dat/tmp/tst/tdir/file4.html  =>  unchanged.
 rm '../tmp/stack/dat/tmp/tst/tdir/file1.html' ? y
 ../tmp/stack/dat/tmp/tst/tdir/file1.html  =>  removed.
 rm '../tmp/stack/dat/tmp/tst/tdir/file2.html' ? y
 ../tmp/stack/dat/tmp/tst/tdir/file2.html  =>  removed.
 rm '../tmp/stack/dat/tmp/tst/tdir/file3.html' ? Y
 ../tmp/stack/dat/tmp/tst/tdir/file3.html  =>  removed.
 rm '../tmp/stack/dat/tmp/tst/tdir/file5.html' ? n
 ../tmp/stack/dat/tmp/tst/tdir/file5.html  =>  unchanged.

This will work, to test if one file size is 0 (you just need to include it in your loop).

myfilesize=`stat -c %s "$FIL"`

if [ $myfilesize = 0 ];then
echo "the file size is zero, do you want to delete it ?"
read -p "yes/no? " -n 1 -r
echo #Move to Next line
if [[ $REPLY =~ ^[Yy]$ ]]
then
    rm "$FIL"
fi
else
echo "File size is not Zero"
fi

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM