This is my first time making a bash script...
I'm trying to make a bash script that will delete the oldest file in a directory until said directory is under a certain size. I want the while look to stop once the directory is under 10000 bytes. 10000 is just for testing; I will increase it later.
du and cut puts the directory size in bytes into the variable called check The while look should run while the file size is greater than 10000 bytes. For each iteration the oldest file in the directory is deleted.
When I run this script, the oldest file is deleted, but it reiterates infinitely even when $check becomes less than 10000. Why does this script keep running infinitely?
check = $(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
while [ $check -gt 10000 ]
check = $(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
do
cd /home/chris/Dropbox/VideoMonitor
ls /home/chris/Dropbox/VideoMonitor -1tr | head -1 | xargs rm
done
This is the output I get once the script has removed all files from the directory.
rm: missing operand
Try 'rm --help' for more information.
And this runs over and over
I would imagine the do
has to be before the reassignment of check
. Otherwise it is not actually part of the body of the loop. Also the assignment should probably be done after the body executes (and before the next test of the loop condition):
check=$(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
while [ $check -gt 10000 ]
do
cd /home/chris/Dropbox/VideoMonitor
ls /home/chris/Dropbox/VideoMonitor -1tr | head -1 | xargs rm
check=$(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
done
I've also removed the spaces around the =
to make your check=...
lines actually assignment statements.
There are two mistakes in your script:
The first mistake is the broken while
clause, it should read
while condition; do
commands
done
or
while condition
do
commands
done
whereas condition
might be a test expression that returns zero or non-zero as you correctly wrote:
[ $check -gt 10000 ]
The line
check = $(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
before the do
is mislocated. I bet you wanted to put it after the do
to get the value again.
The second mistake is your xargs
usage. Since the list of files you want to pass to xargs
might be empty, you'd add the switch --no-run-if-empty
to fix the rm: missing operand
error.
To avoid writing the check
line twice you could write a while-true loop and check the condition inside and break out of the loop, since bash has no head-controlled while-loop.
while [ true ]; do
check = ...
if [ $check -le 10000 ]; then
break
fi
...
done
Other sugestions
cd
every time in the loop, do it before find -mtime +N
(find files with modification date older ( +
) than N
days) pushd
and popd
are very convinient over cd
because cd
has changed the directory after script execution you'd need to remember the previous directory to cd back. With
cd back. With
pushd you tell bash to do set the current directory where
popd` brings you back to the previous directory. On directory stack functions There are two commands in your while-loop clause, [ $check -gt 10000 ]
and check = $(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
(which is a bad command and not an asssignment because of the spaces around the =
-sign) . The latter command is the only one that determines if the while loop ever terminates. If its return code is always 0 then the while loop never finishes..
If there are no files then the rm
command has no operand and hence the error message..
Don't put spaces around the = in assignments
check=$(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
while [ $check -gt 10000 ]
check = $(du -sb /home/chris/Dropbox/VideoMonitor | cut -f1)
do
cd /home/chris/Dropbox/VideoMonitor
ls /home/chris/Dropbox/VideoMonitor -1tr | head -1 | xargs rm
done
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.