bashmaildir

Renaming Maildir Messages as "Read" or Not Read


i need to manage my server's maildir messages.

i need to know how i can efficiently rename individual message files as already [R]ead, or vice versa, preferably using standard bash.

1408429273.V825I1cce0a1M366263.server0:2,S
1408500713.V825I1ccddaaM341812.server0:2,S
1408502356.V825I1ccddf3M195155.server0:2,S
1408502501.V825I1cce048M253486.server0:2,RS

if a file is already marked as [R]ead, i don't want to trip over it again, or worse, rename it wrongly.


Solution

  • Try:

    #!/bin/bash
    shopt -s nullglob
    for F in /path/to/files/*:*,*; do
        CODE=${F##*,}
        [[ $CODE != *R* ]] && echo mv "$F" "${F%,*},R${CODE}"
    done
    

    Remove echo when confirmed that it's working.

    More strict:

    #!/bin/bash
    shopt -s nullglob
    shopt -s extglob
    for F in /path/to/files/*:+([0-9]),*([A-Z]); do
        CODE=${F##*,}
        [[ $CODE != *R* ]] && echo mv "$F" "${F%,*},R${CODE}"
    done
    

    To rename as not read:

    #!/bin/bash
    shopt -s nullglob
    shopt -s extglob
    for F in /path/to/files/*:+([0-9]),*([A-Z]); do
        CODE=${F##*,}
        [[ $CODE == *R* ]] && echo mv "$F" "${F%,*},${CODE//R}"
    done
    

    Script:

    #!/bin/bash
    
    shopt -s extglob
    
    CHANGE_MODE=''
    FILES=()
    
    function show_usage_and_exit {
        echo "Usage: $0 option [--] file [file2 ...]" >&2
        echo "Options:" >&2
        echo "  -r, --read    Add read flag to filenames." >&2
        echo "  -u, --unread  Remove read flag from filenames." >&2
        exit 1
    }
    
    while [[ $# -gt 0 ]]; do
        case "$1" in
        -r|--read)
            CHANGE_MODE='R'
            shift
            ;;
        -u|--unread)
            CHANGE_MODE='U'
            shift
            ;;
        -h|--help)
            show_usage_and_exit
            ;;
        --)
            shift
            FILES+=("$@")
            break
            ;;
        -*)
            echo "Invalid option: $1" >&2
            show_usage_and_exit
            ;;
        *)
            FILES+=("$1")
            ;;
        esac
        shift
    done
    
    if [[ -z $CHANGE_MODE ]]; then
        echo "No mode specified."
        show_usage_and_exit
    elif [[ ${#FILES[@]} -eq 0 ]]; then
        echo "No file was specified."
        show_usage_and_exit
    else
        for F in "${FILES[@]}"; do
            if [[ ! -f $F ]]; then
                echo "File does not exist or is not a file: $F" >&2
                exit 1
            elif [[ $F != *:+([0-9]),*([A-Z]) ]]; then
                echo "File format is not recognized: $F" >&2
                exit 1
            fi
        done
    fi
    
    if [[ $CHANGE_MODE == R ]]; then
        for F in "${FILES[@]}"; do
            CODE=${F##*,}
            [[ $CODE != *R* ]] && echo mv "$F" "${F%,*},R${CODE}"
        done
    else
        for F in "${FILES[@]}"; do
            CODE=${F##*,}
            [[ $CODE == *R* ]] && echo mv "$F" "${F%,*},${CODE//R}"
        done
    fi