I'm not used to linux scripting and this is the first time I'm working on it so I'm struggling with the following problem:
Code:
while [ $pct -gt 80 ]; do
flag=1;
ls -tr | while read file; do
if [[ $file =~ .+\.log[0-9]+ ]]; then
printf "File deleted:\n";
stat $file;
rm -r $file;
flag=1;
break;
else
flag=0;
fi;
done;
if [ $flag -eq 0]; then
break;
fi;
pct= # get the new pct;
done;
The operation is to delete certain log files as captured by the above regular expression, in order of oldest files first and hence I'm using ls -tr. I'm iterating over the list of files using the while loop and if any file matches with the given regex, I'm deleting it. After every deletion I'm checking the percentage of the application file system used and if it is greater than 80% (as shown in outer while loop condition), I repeat the process.
Now often, even after deleting the files, the percentage used doesn't go below 80%, even though no files with the given regex pattern is left and I cannot delete the other remaining files in the same folder. So, it goes into an infinite loop and hence I'm trying to use a flag variable to break the infinite loop in such cases. However, since I'm using pipe to iterate over the files, it becomes a sub-shell or a child process and the flag variable is not available (updated value of flag from sub shell does not reflect in parent shell) in the parent process (it's what I read in an article about piping) and thus the infinite loop is never broken. Can anyone please suggest a fix around this or an alternate logic?
ls | while
loop ever only touches one file listed byls
, so I think you could just use something likefile=$(ls -tr | grep '\.log[0-9]+' | head -1)
to get the first matching filename. Or an empty string if there are none. Of course that won't work if your filenames are messy enough (in particular, newlines are valid in filenames), but I guess you know you only have simple filenames. In addition, if the files are created so that their names sort in order, you could just let the shell glob the names and pick the first in the list, since globs sort lexicographically. – ilkkachu Jun 30 '22 at 19:32grep
work? It doesn't change the order. (The regex should be.\.[0-9]+
, though. Note that the regex match isn't anchored to the start or end of the string.) And yes, if the names of the files don't sort in the same order as their timestamps, then you can't use just that. But if the files are named so that they contain e.g.YYYY-MM-DD
dates and times, or just monotonically increasing numbers, then they do sort the same as their timestamps. Well, assuming they're not modified after the next file is created, but that's usually how log files work anyway. – ilkkachu Jun 30 '22 at 19:52file=$(ls -tr | grep '\.log[0-9]+' | head -1)
seemed like a possible solution, but I used it only to get blank output. It's not showing anything,$file
is blank. Sorry, I don't understand how else to make it work since as I said this is very new for me. So if there is any other solution, I'd be grateful to you. Thanks. – Biswadeep Sarkar Jun 30 '22 at 19:59grep -E '\.log[0-9]+'
. – ilkkachu Jun 30 '22 at 20:50