LINUX.ORG.RU

История изменений

Исправление ZyX, (текущая версия) :

К сожалению, ещё нет. Это требует реализации файловых операций вручную, а не внешними утилитами. Подходящих библиотек на C (не комбайнов вроде gtk или того, что есть у Apache) для этого найти не удалось. Планирую иметь первоначальную реализацию в каком-то виде в следующем релизе (по умолчанию будет включёна текущая реализация).

Есть хак с парсингом вывода strace: можно подсчитать, сколько байтов надо скопировать, а потом считать, сколько байтов было записано (strace -e write после “=” выдаёт количествой записанных байт). Правда, мой вариант (cp_p: CP with Progress bar, ниже), работает не всегда корректно.

#!/bin/zsh
set -A SOURCES
typeset -g \
    DEREFERENCE=""
typeset -gi \
    DOHARDLINKS=0 \
    DOSYMLINKS=0 \
    ONEFILESYSTEM=0
typeset -ga SOURCES
function parse_args()
{
    local -i SKIP=0
    local -i HAS_TARGETDIR=0
    local LASTSOURCE=""
    for arg in $@
    do
        if (( SKIP ))
        then
            SKIP=0
            continue
        fi
        if [[ "$arg" =~ "^-.*" ]]
        then
            case $arg in
                --no-preserve|--reply|--sparce|--target-directory|-S|--suffix|-V|--version-control)
                SKIP=1 ;;
                --*)
                    [[ "$arg" == "--link"            ]] && DOHARDLINKS=1
                    [[ "$arg" == "--dereference"     ]] && DEREFERENCE="-L"
                    [[ "$arg" == "--no-dereference"  ]] && DEREFERENCE=""
                    [[ "$arg" == "--symbolic-link"   ]] && DOSYMLINKS=1
                    [[ "$arg" == "--one-file-system" ]] && ONEFILESYSTEM=1 ;;
                -*) [[ "$arg" =~ "H"    ]] && DEREFERENCE="-D"
                    [[ "$arg" =~ "L"    ]] && DEREFERENCE="-L"
                    [[ "$arg" =~ "[Pd]" ]] && DEREFERENCE=""
                    [[ "$arg" =~ "l"    ]] && DOHARDLINKS=1
                    [[ "$arg" =~ "s"    ]] && DOSYMLINKS=1
                    [[ "$arg" =~ "x"    ]] && ONEFILESYSTEM=1 ;;
            esac
            [[ "$arg" =~ "^--target-directory" ]] &&
                HAS_TARGETDIR=1
        else
            [[ -z "$LASTSOURCE" ]] || SOURCES=( $SOURCES "$LASTSOURCE" )
            LASTSOURCE="$arg"
        fi
    done
    (( HAS_TARGETDIR )) && SOURCES=( $SOURCES $LASTSOURCE )
    typeset -gr DEREFERENCE DOHARDLINKS DOSYMLINKS ONEFILESYSTEM SOURCES
}
function main()
{
    parse_args $@
    typeset -a KEYS
    (( ONEFILESYSTEM )) && KEYS=( -x )
    [[ -z "$DEREFERENCE"   ]] || KEYS=( $KEYS $DEREFERENCE )
    if (( ! ( DOHARDLINKS || DOSYMLINKS ) ))
    then
        local PGBAR FIFO
        local -i line LENGTH WRITTEN=0 OLDLENGTH=-1 OLDPERCENT=-1 \
            BYTES=$(du --count-links --total -b $KEYS $SOURCES | tail -n 1 | \
                                                            awk "{ print \$1 }")
        # if [[ -p $HOME/.settings/cp_p-fifo ]]
        # then
            # FIFO=$HOME/.settings/cp_p-fifo
        # else
            # FIFO=$(mktmp -u)
            # mkfifo $FIFO
        # fi
        # strace -o $FIFO -q -ewrite cp $@ >/dev/null &
        # trap "kill -INT $! ; exit" INT
        # cat $FIFO | grep "^write" | grep -o "[[:digit:]]\\+\$" | \
        ( sleep 0.1s && exec cp $@ ) &
        trap "kill -INT $! ; exit" INT
        strace -q -ewrite -p$! 2>&1 | grep "^write" | \
                                      grep -o "[[:digit:]]\\+\$" | \
            while read line
            do
                (( WRITTEN+=line ))
                (( LENGTH  = ((COLUMNS-7)*WRITTEN)/BYTES ))
                (( PERCENT =         (100*WRITTEN)/BYTES ))
                (( LENGTH==OLDLENGTH && PERCENT==OLDPERCENT )) && continue
                (( OLDPERCENT=PERCENT ))
                echo -n "["
                (( LENGTH > 1 && LENGTH!=OLDLENGTH )) && PGBAR="${PGBAR}="
                (( OLDLENGTH=LENGTH ))
                echo -n ${PGBAR}
                (( LENGTH )) && echo -n ">"
                printf "%*s] %*u%%\r" $(( COLUMNS-7-LENGTH )) "" 3 \
                                      $PERCENT
            done
    else
        cp $@
    fi
}
main $@

Исходная версия ZyX, :

К сожалению, ещё нет. Это требует реализации файловых операций вручную, а не внешними утилитами. Подходящих библиотек на C (не комбайнов вроде gtk или того, что есть у Apache) для этого найти не удалось. Планирую иметь первоначальную реализацию в каком-то виде в следующем релизе (по умолчанию будет включёна текущая реализация).

Есть хак с парсингом вывода strace: можно подсчитать, сколько байтов надо скопировать, а потом считать, сколько байтов было записано (strace -e write[/inlite] после “=” выдаёт количествой записанных байт). Правда, мой вариант (cp_p: CP with Progress bar, ниже), работает не всегда корректно.

#!/bin/zsh
set -A SOURCES
typeset -g \
    DEREFERENCE=""
typeset -gi \
    DOHARDLINKS=0 \
    DOSYMLINKS=0 \
    ONEFILESYSTEM=0
typeset -ga SOURCES
function parse_args()
{
    local -i SKIP=0
    local -i HAS_TARGETDIR=0
    local LASTSOURCE=""
    for arg in $@
    do
        if (( SKIP ))
        then
            SKIP=0
            continue
        fi
        if [[ "$arg" =~ "^-.*" ]]
        then
            case $arg in
                --no-preserve|--reply|--sparce|--target-directory|-S|--suffix|-V|--version-control)
                SKIP=1 ;;
                --*)
                    [[ "$arg" == "--link"            ]] && DOHARDLINKS=1
                    [[ "$arg" == "--dereference"     ]] && DEREFERENCE="-L"
                    [[ "$arg" == "--no-dereference"  ]] && DEREFERENCE=""
                    [[ "$arg" == "--symbolic-link"   ]] && DOSYMLINKS=1
                    [[ "$arg" == "--one-file-system" ]] && ONEFILESYSTEM=1 ;;
                -*) [[ "$arg" =~ "H"    ]] && DEREFERENCE="-D"
                    [[ "$arg" =~ "L"    ]] && DEREFERENCE="-L"
                    [[ "$arg" =~ "[Pd]" ]] && DEREFERENCE=""
                    [[ "$arg" =~ "l"    ]] && DOHARDLINKS=1
                    [[ "$arg" =~ "s"    ]] && DOSYMLINKS=1
                    [[ "$arg" =~ "x"    ]] && ONEFILESYSTEM=1 ;;
            esac
            [[ "$arg" =~ "^--target-directory" ]] &&
                HAS_TARGETDIR=1
        else
            [[ -z "$LASTSOURCE" ]] || SOURCES=( $SOURCES "$LASTSOURCE" )
            LASTSOURCE="$arg"
        fi
    done
    (( HAS_TARGETDIR )) && SOURCES=( $SOURCES $LASTSOURCE )
    typeset -gr DEREFERENCE DOHARDLINKS DOSYMLINKS ONEFILESYSTEM SOURCES
}
function main()
{
    parse_args $@
    typeset -a KEYS
    (( ONEFILESYSTEM )) && KEYS=( -x )
    [[ -z "$DEREFERENCE"   ]] || KEYS=( $KEYS $DEREFERENCE )
    if (( ! ( DOHARDLINKS || DOSYMLINKS ) ))
    then
        local PGBAR FIFO
        local -i line LENGTH WRITTEN=0 OLDLENGTH=-1 OLDPERCENT=-1 \
            BYTES=$(du --count-links --total -b $KEYS $SOURCES | tail -n 1 | \
                                                            awk "{ print \$1 }")
        # if [[ -p $HOME/.settings/cp_p-fifo ]]
        # then
            # FIFO=$HOME/.settings/cp_p-fifo
        # else
            # FIFO=$(mktmp -u)
            # mkfifo $FIFO
        # fi
        # strace -o $FIFO -q -ewrite cp $@ >/dev/null &
        # trap "kill -INT $! ; exit" INT
        # cat $FIFO | grep "^write" | grep -o "[[:digit:]]\\+\$" | \
        ( sleep 0.1s && exec cp $@ ) &
        trap "kill -INT $! ; exit" INT
        strace -q -ewrite -p$! 2>&1 | grep "^write" | \
                                      grep -o "[[:digit:]]\\+\$" | \
            while read line
            do
                (( WRITTEN+=line ))
                (( LENGTH  = ((COLUMNS-7)*WRITTEN)/BYTES ))
                (( PERCENT =         (100*WRITTEN)/BYTES ))
                (( LENGTH==OLDLENGTH && PERCENT==OLDPERCENT )) && continue
                (( OLDPERCENT=PERCENT ))
                echo -n "["
                (( LENGTH > 1 && LENGTH!=OLDLENGTH )) && PGBAR="${PGBAR}="
                (( OLDLENGTH=LENGTH ))
                echo -n ${PGBAR}
                (( LENGTH )) && echo -n ">"
                printf "%*s] %*u%%\r" $(( COLUMNS-7-LENGTH )) "" 3 \
                                      $PERCENT
            done
    else
        cp $@
    fi
}
main $@