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.