[colug-432] Gracefully Doing Nothing

jep200404 at columbus.rr.com jep200404 at columbus.rr.com
Wed Feb 8 20:02:39 EST 2017


On Mon, 30 Jan 2017 10:37:07 -0800, Rick Hornsby <richardjhornsby at gmail.com> wrote:

> [> ]On January 30, 2017 at 11:57:53, jep200404 at columbus.rr.com (
> [> ]jep200404 at columbus.rr.com) wrote:
> 
> [> ]How does one do nothing gracefully in a Bourne shell for loop?

> Typically, I'd think of two approaches to this.
> The first is just to throw away any error output.
> That's probably not ideal, because in case something
> goes wrong (destination volume full, etc) you won't know.

Yup. That's not graceful.

> The other is to generate an array of files, then wrap your loop in an if
> statement. "if" might not seem super cool, but it might do the trick for
> you:

> $ cat backup.sh
> prefix=<set the date or whatever>
> files=([a-z]*)
> if [ -e "${files[0]}" ]; then
>     for f in "${files[@]}"; do
>         mv "$f" "$prefix-$f"
>     done
> fi

Yes. We have all had to do stuff like that. 
It is not graceful.

> An option that might be slightly less readable but could be done in fewer
> lines (eliminates the explicit loop construct entirely) is to use `find`
> with exec mv or xargs. I haven't tested this, so consider it metacode -

> find . -name '^[a-z]*' -maxdepth 1 -exec mv "{}" "$prefix-{}" \;

That gracefully does nothing, and does so with Bourne shells.
Another nice thing about that is that it does not crash
when there are a large number of files.

Initially I had a for loop with shopt -s nullglob
inspired by Jeff Frontz.

Today, for a different task, I settled on the following technique,
similar to your find technique.

    find ... | while read f; do echo do something with "$f";done

shown more fully below

    doj at pan:~ $ head -n 1000 -v .foo_config bin/delete-log-files bin/delete-files
    ==> .foo_config <==
    mybin="$HOME/bin"
    PATH="$PATH:$mybin"
    log_dir="$HOME/logs"
    minimum_log_space=10000000 ;# Unit is 1024 bytes.
    deletable_log_filename_glob='[0-9]*'

    ==> bin/delete-log-files <==
    #!/bin/sh

    . "$HOME/.foo_config"

    find "$log_dir" -name "$deletable_log_filename_glob" |
    sort |
    delete-files ~/logs "$minimum_log_space"

    ==> bin/delete-files <==
    #!/bin/sh

    if [ "$#" -lt 2 ]; then
        exec >&2
        echo Deletes files while df reports space is less than minimum_space.
        echo Filenames are specified on stdin, one filename per line.
        echo
        echo Usage: `basename "$0"` directory minimum_space
        echo
        echo     minimum_space unit is 1024 bytes.
        echo
        echo 'e.g., find ~/logs -name '\''[0-9]*'\'' | sort |'
        echo delete-files ~/logs 09764200
        exit 1
    fi

    dir="$1"
    minimum_space="$2"

    while read f; do
        space=`df --output=avail "$dir" | grep -v '[A-Z][a-z][a-z]*'`
        # echo $0 $dir $space $minimum_space if [ "0$space" -ge "0$minimum_space" ]
        if [ "0$space" -ge "0$minimum_space" ]; then
            # echo $?
            # echo ok
            break
        fi

        # echo $?
        # echo low [ "0$space" -ge "0$minimum_space" ]
        # echo rm "$f"
        rm "$f"
        # sleep .1
    done
    doj at pan:~ $


More information about the colug-432 mailing list