Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Ok i have requested a code here but initial i didn't ask to make it busybox compatible. My bad. I'm new to linux and coding.

The code needs to do the following:

Delete 50GB of oldest data (dir with files) from a directory when the HD reaches a capacity of 95%.

The code they gave me is, that is not working with busybox:

DIRS="a/ b/"
MAXDELBYTES="53687091200" # 50GB
DELBYTES="0"

find $DIRS -type f -printf "%T@ %s %p\n" | sort -r -n | while read time bytes filename
do
    rm -fv "$filename"
    DELBYTES=$((DELBYTES + bytes))

    if [ $DELBYTES -ge $MAXDELBYTES ]; then break; fi
done

What is not working:

  • -printf (changed it to -print)
  • %T@ %s %p\n (dont know what to change it to)
  • Do not know what else isn't working. I'm new to coding and linux.

Now this need to be translated to busybox so it will work on my embed linux system. Also a cron command needs to be added so it runs every Friday.

Thanks for your support!

share|improve this question
    
Is there another way to let this work in busybox, even when the filename has spaces? –  Jasper Aug 23 '12 at 8:00
    
You cannot simply change printf to print and expect the command to do the same afterwards. printf is needed for sorting the output later. You seem to have a non-GNU version of find which has no -printf option, so it won't work that way on your system. –  scai Aug 23 '12 at 11:42
    
@warl0ck No, it won't. In the read command, everything after the bytes field will be assigned to the last variable: filename. The rm has quotes around $filename, so everything should work with spaces. It would, however, fail in case of filenames with linebreaks in names. –  rozcietrzewiacz Aug 23 '12 at 14:04

2 Answers 2

up vote 4 down vote accepted

Since the busybox implementation of find does not offer custom output formatting, you need to outsource the formatting task to a separate program :) Luckily, even busybox includes the handy stat command. It's output format fields differ from the ones that GNU find uses, so the symbols you need to use are different. The script below assumes that find and stat are those that come from busybox.

DIRS="a/ b/"
MAXDELBYTES="53687091200" # 50GB
DELBYTES="0"

find $DIRS -type f -exec stat -c "%Y %s %n" {} \; | sort -r -n | while read time bytes filename
do
    rm -fv "$filename"
    DELBYTES=$((DELBYTES + bytes))

    if [ $DELBYTES -ge $MAXDELBYTES ]; then break; fi
done

As always, read each command's description before you use it. In case of busybox, you won't find manpages for them, but you can use --help to display usage information.

Be warned, that this solution can break things in an unlikely situation, when file names contain newline symbols in them! This should not occur on a healthy system, but might happen, for instance, if someone manages to either break into the system or exploit some vulnerability that allows arbitrary file creation.

To prevent accidentally removing useful files in such cases, you should first find and remove all files that include newlines in their names. To list those, run:

find / -name "*
*"

(There is only a newline between the asterisks.) Then, when you're sure all those files are not needed, delete them using either

find / -name "*
*" -delete

or

find / -name "*
*" -print0 | xargs -0 rm -vf

Both should work with busybox.

share|improve this answer
    
Thanks a lot. Does it also delete folders in that directory? or only files? I get following error: code: find: stat: No such file or directory - so it means it halts with stat. Or does it mean my HD is not full for 95% –  Jasper Aug 23 '12 at 19:16
3  
@Jasper That means your Busybox doesn't include the stat utility. Busybox is highly tunable, many features are optional. –  Gilles Aug 23 '12 at 19:27
    
Ah dammit! It is for the linux build "OpenElec." A lightweight XBMC version (media center). I guess the only solution is to ask if they can add support for stat in a future release? Or can i add this myself? –  Jasper Aug 23 '12 at 19:51
    
WOW that was fast. They added it in the next release: github.com/OpenELEC/OpenELEC.tv/commit/… Will report back to you when i tested this script in next beta release from Openelec.. –  Jasper Aug 23 '12 at 20:50

Generally, it's a bad idea to parse the output of ls. But on an embedded system that has no stat, no zsh, no find -printf, no perl or other large scripting language, it's the only way of sorting files by date. Assuming that your file names contain no whitespace and none of \'" (which xargs mangles) — an assumption that your original script makes — you can use xargs ls -str to display files sorted by date, and display their size in the process.

find $DIRS -type f |
xargs ls -str |
while read kilobytes filename; do …

Note that the size is displayed in kilobytes instead of bytes. Furthermore, this is the on-disk space taken by the file rather than the number of bytes in the file. Usually, this number is the file size, rounded up to the next integer number of blocks, but it may be less if the file is sparse. In a script that frees disk space, this is probably what you want.

There is a big caveat with the script above: it will only print its results in the right order if the number of files is small enough that xargs can make a single call to ls. If there are multiple calls to ls, each call will sort its arguments separately. You can print the file dates with ls, but sorting this human-readable output is very complicated. A better solution to at least detect the error case is to substitute the output of find into the command line.

{ set -f; IFS='
'; ls -str $(find $DIRS -type f); } |
while read -r kilobytes filename; do …
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.