Переименуйте файлы путем постепенного увеличения числа в имени файла

Самый простой путь состоял бы в том, чтобы вручить сборку .config файл с необходимыми опциями. Это, конечно, потребовало бы, чтобы все параметры конфигурации были даны, таким образом, это будет применимо в случае незначительных изменений к созданному в интерактивном режиме существующему .config файл.

Если Вы спрашиваете об использовании тока .config но только изменяя некоторые флаги через make, чем я не знаю. Но Вы могли бы попытаться отредактировать .config файл с помощью сценария и затем выполненный make.

12
11.06.2012, 17:04
6 ответов

Я думаю, что это должно сделать работу:

#!/bin/bash

NEWFILE=$1

for file in `ls|sort -g -r`
do
    filename=$(basename "$file")
    extension=${filename##*.}
    filename=${filename%.*}

    if [ $filename -ge $NEWFILE ]
    then
        mv "$file" "$(($filename + 1))".$extension
    fi
done

Сценарий берет один параметр - число Вас новое изображение.

PS. Поместите сценарий в другой каталог, чем Ваши изображения. В каталоге изображений должны быть только изображения, названные таким образом, что Вы описали.

9
27.01.2020, 19:56
  • 1
    Это выглядит многообещающим, я попробую его через несколько часов, когда я вернусь на своем ноутбуке. –  robertc 11.06.2012, 19:33
  • 2
    Это будет только работы, если Ваше имя файла не будет снабжено префиксом символами –  mems 15.11.2016, 20:35
  • 3
    @mems OP ясно указывает, что имена файлов начинаются с числа –  xhienne 08.01.2017, 15:16

Это было бы легче в zsh, где можно использовать

  • On спецификатор шарика для сортировки соответствий в порядке убывания (и n использовать числовой порядок, в случае, если имена файлов все не имеют продвижения, обнуляет к той же ширине);
  • (l:WIDTH::FILLER:) расширение параметра отмечает для заполнения всех чисел к той же ширине (ширина большего числа).
break=$1   # the position at which you want to insert a file
setopt extended_glob
width=
for x in [0-9]*(nOn); do
  n=${x%%[^0-9]*}
  if ((n < break)); then break; fi
  ((++n))
  [[ -n $width ]] || width=${#n}
  mv $x ${(l:$width::0:)n}${x##${x%%[^0-9]*}}
done

В ударе вот сценарий, который предполагает, что файлы дополнены к фиксированной ширине (иначе, сценарий не переименует правильные файлы), и клавиатуры к фиксированной ширине (который должен быть указан).

break=$1      # the position at which you want to insert a file
width=9999    # the number of digits to pad numbers to
files=([0-9]*)
for ((i=#((${#files}-1)); i>=0; --i)); do
  n=${x%%[^0-9]*}
  x=${files[$i]}
  if ((n < break)); then continue; fi
  n=$((n + 1 + width + 1)); n=${n#1}
  mv -- "${files[$i]}" "$n${x##${x%%[^0-9]*}}"
done
2
27.01.2020, 19:56

Эта точная проблема охвачена в этой статье. Обратите внимание, что необходимо было бы изменить его для поддержки SVG и форматов PNG путем добавления второго шага мВ.

1
27.01.2020, 19:56
  • 1
    , я не думаю, что это - точная проблема, это идет, перенумеровывают все изображения каждый раз. Я просто хочу перенумеровать изображения от конкретной точки. –  robertc 11.06.2012, 19:30

Легче:

touch file`ls file* | wc -l`.ext

Вы получите:

$ ls file*
file0.ext  file1.ext  file2.ext  file3.ext  file4.ext  file5.ext  file6.ext
1
27.01.2020, 19:56

Похоже, в последнее время этот вопрос не вызывает большого интереса, но если кто-то наткнется на него, здесь есть три проблемы.

  • Одна из них заключается в том, как выбирать файлы для переименования на основе семантических критериев (диапазон не является лексическим и не может быть указан с помощью подстановочных знаков или даже регулярных выражений --теория автоматов говорит, что это сложнее, чем NFA ).

  • Во-вторых, как изменить имя, изменив его часть.

  • В-третьих, как избежать конфликта имен.

Сценарий в Bash и многих других языках может выполнять это конкретное преобразование, но большинству из нас не нужно писать программу каждый раз, когда мы хотим переименовать группу файлов.

С моим (бесплатным и открытым исходным кодом)rene.pyвы можете делать все, что хотите, но требуется два вызова, чтобы избежать проблемы конфликта имен.

  1. Первый
    rene ?.*/#7-80  %?.* B
    
    увеличивает все имена в диапазоне, добавляя префикс %, чтобы избежать существующих имен.
  2. Тогда
    rene %* *
    
    удаляет этот префикс из тех файлов, в которых он есть.

Я описываю это вhttps://sourceforge.net/p/rene-file-renamer/discussion/examples/thread/f0fe8aa63c/

3
27.01.2020, 19:56

Если вы сохраните следующий скрипт как renn.sh, после установки его (см. справку о том, как его установить ), вы сможете использовать:

renn "@." "[(02)i+1]." "{i -ge 5}" '<dir_path>'

Чтобы узнать, как использовать скрипт, вы можете вызвать его с флагом --help.

# REName with Numbers - a.sh (dash; bash; zsh - compatible) rename script 
# that can do basic arithmetic operations (+, -, padding with 0's) on 
# numbers in file names

# Disclaimer:
# By using this program you are assuming full responsibility (and the 
# author of this program shall not be held liable) for any data loss 
# or damage that may result from the use or misuse of this program.

DetectShell () {
    eval $1=\"\";
    if [ -n "$BASH_VERSION" ]; then
        eval $1=\"bash\";
    elif [ -n "$ZSH_VERSION" ]; then
        eval $1=\"zsh\";
    elif [ "$PS1" = '$ ' ]; then
        eval $1=\"dash\";
    else
        eval $1=\"undetermined\";
    fi
}

GetCharsArray () {
    DestroyArray $2

    eval str=\"\$$1\"
    i1=0;
    qm_mask=""
    if [ -z "$str" ]; then
        eval $2\_0="0";
    else
        rem_str="$str"
        while [ "$i1" -le 1000000000 ]; do
            i1=$((i1+1));
            rem_str="${rem_str#?}"
            qm_mask="$qm_mask?"
            if [ -z "$rem_str" ]; then
                break;
            fi
        done
        eval $2\_0="$i1"
        i2=1;
        while [ "$i2" -le "$i1" ]; do
            qm_mask="${qm_mask#?}"
            eval crt_char=\"\$\{str\%$qm_mask\}\"
            str="${str#?}"
            eval $2\_$i2="\"\$crt_char\""
            i2=$((i2+1))
        done
    fi
}

GetStrLen () {
    eval str=\"\$$1\"
    str_len=0;
    qm_mask=""
    if [ -z "$str" ]; then
        eval $2="0";
    else
        rem_str="$str"
        while [ "$str_len" -le 1000000000 ]; do
            str_len=$((str_len+1));
            rem_str="${rem_str#?}"
            qm_mask="$qm_mask?"
            if [ -z "$rem_str" ]; then
                break;
            fi
        done
        eval $2="$str_len"
    fi
}

DestroyArray () {
    eval array_len=\$\(\($1\_0\)\)

    j=0;
    while [ "$j" -lt "$array_len" ]; do
        j=$((j+1))
        unset $1\_$j
    done
    unset $1\_0
}

ValidateNaturalNumber () {
    eval tested_number=\"\$$1\"
    condition="\$tested_number -ge 0" #test if natural number
    result="true"
    if [ -n "$tested_number" ]; then
        eval [ $condition ] 2>/dev/null || {
            result="false";
        }
    fi
    eval $2=$result
}

ProcedureGetMarginsAndNumber () {

    eval input_f_n=\"\$$1\"

    neg_number_detected="false"

    if [ -n "$pylon1_mask1" ]; then
        margin1="${input_f_n%%"$pylon1_mask1"*[0-9]*"$pylon2_mask1"*}"
    else
        if [ "${input_f_n%%"-"[0-9]*"$pylon2_mask1"*}" = "$input_f_n" ]; then #if a negative number is not match:
            margin1="${input_f_n%%[0-9]*"$pylon2_mask1"*}"
        else #if a negative number is match:
            margin1="${input_f_n%%"-"[0-9]*"$pylon2_mask1"*}"

            neg_number_detected="true"
        fi
    fi
    if [ -n "$pylon2_mask1" ]; then
        margin2="${input_f_n##"$margin1""$pylon1_mask1"*[0-9]*"$pylon2_mask1"}"
    else
        if [ "$neg_number_detected" = "false" ]; then #if a negative number is not match:
            margin2="${input_f_n##"$margin1""$pylon1_mask1"*[0-9]}"
        else #if a neg number is match:
            margin2="${input_f_n##"$margin1""$pylon1_mask1"*"-"[0-9]}"
        fi
    fi

    number_temp="${input_f_n#"$margin1""$pylon1_mask1"}"
    number="${number_temp%"$pylon2_mask1""$margin2"}"
}

PrintInTitle () {
    printf "\033]0;%s\007" "$1"
}

PrintJustInTitle () {
    PrintInTitle "$1">/dev/stdin
}

CleanUp () {

    #Restore CTRL-C, CTRL-Z:
    trap - INT
    trap - TSTP

    DestroyArray params
    DestroyArray rn_from
    DestroyArray rn_to
    DestroyArray numbers
    DestroyArray margin1
    DestroyArray margin2
    DestroyArray marks_temp_fns
    DestroyArray coll_chk_1_markings
    DestroyArray marks_special_temp_fns

    #Restore the initial directory:
    cd "$initial_dir"

    #Clear the title:
    PrintJustInTitle ""

    #Restore IFS:
    IFS="$old_IFS"
}

trap1 () {
    if [ "$started_rn" = "false" ]; then
        printf "Cleaning up. Please wait..."
        CleanUp
        SPACE=" "
        BS="\b"
        SPACE_str=""
        BS_str=""
        for i in $(seq 1 40); do SPACE_str="$SPACE_str""$SPACE"; done
        for i in $(seq 1 40); do BS_str="$BS_str""$BS"; done
        printf "$BS_str"
        printf "$SPACE_str"
        printf "$BS_str"
        printf "Aborted. Nothing done.\n"
        exit
    fi
}

DisplayHelp () {
    printf "\n"
    printf "renn - REName with Numbers\n"
    printf "\n"
    printf "    Description:\n"
    printf "        - renames filenames in a directory that match a mask (<mask1>) inexactly:\n"
    printf "            - e.g.: <mask1>=\"(@)\" matches \"*(@)*\"\n"
    printf "            - a '@' wildcard represents a number in the matched file/folder names.\n"
    printf "            - note that the first match is taken into consideration - so the strings surrounding the '@' mask character should uniquelly identify the matched number in each file/folder name\n"
    printf "\n"
    printf "    Syntax:\n"
    printf "    renn <mask1> <mask2> <directory_path> [<condition>] [flags]\n"
    printf "        where:\n"
    printf "        <mask1> is a string containing exactly one '@' wildcard.\n"
    printf "        <mask2> is a string containing one \"[...]\" arithmetic expression.\n"
    printf "            An arithmetic expression is of the form \"[expr(i)]\", where:\n"
    printf "                \"i\" is a variable containing the number that the \"@\" wildcard replaces for each file/folder name\n"
    printf "                \"expr(i)\" represents an arithmetic expression containing any of: the variable \"i\" (without the \$ in front of it), \"-\", \"+\", \"(\", \")\", SPACE, TAB. Note that only addition and substraction are permitted - this is with of scope of not loosing information from file names\n"
    printf "                To pad the current arithmetic expression evaluation (\"expr(i)\") with N zeroes use the syntax: \"[(0N)expr(i)]\"\n"
    printf "            Example of arithmetic expression: [i+1]\n"
    printf "        <directory_path> represents the directory in which to try to match <mask1> and in which to perform the rename operation.\n"
    printf "        <condition>:\n"
    printf "            A { <condition> } has the syntax of an \"if [ <condition> ]; then\" statement, in which \"-o\" (logical OR) and \"-a\" (logical AND) can be used, except for the fact that the variable \"i\" is used without the character \$ in front (i.e.: i and not \$i). See above what \"i\" represents.\n"
    printf "            Like with the \"if\" syntax, subconditions can be grouped with escaped paranthesis: \(, \)\n"
    printf "            For example: { \(i -ge 10 -a i -le 100\) -o \(i -ge 210 -a i -le 300\) } - represents a valid condition\n"
    printf "        [flags] can be:\n"
    printf "            --help or -h\n"
    printf "                Displays this help information\n"
    printf "            --install or -i\n"
    printf "                Creates an executable symbolic link, in the location (directory) of the script\n"
    printf "            --file or -f\n"
    printf "                Tries to match file names (default)\n"
    printf "            --dir or -d\n"
    printf "                Tries to match directory names\n"
    printf "            --preview or -p\n"
    printf "                Previews the rename operation instead of properly renaming\n"
    printf "\n"
    printf "    Recommendations/Notes:\n"
    printf "       To avoid unexpected behaviour, always quote parameters.\n"
    printf "       In order for this program to work correctly: new files must not be added and files must not be renamed/deleted in \"<directory_path>\", while the program is running!\n"
    printf "       Also, the rename operation shall not be interrupted (there are two major steps: Analyze and Preview/Rename).\n"
    printf "       For more complex file name opperations, this script can be used together with the \"mmv\" utility\n"
    printf "       Please note that: if they contain the newline character in them:\n"
    printf "        - file names are ignored\n"
    printf "        - masks are not handled properly\n"
    printf "       When temporary file name collision is detected, the \"▄\" character is used at the beginning of the file names for two step rename\n"
    printf "\n"
}


## MAIN START ##

#Store initial IFS:
old_IFS="$IFS"
IFS=" $(printf "\t")
";

started_rn="false"
E="ERROR"

DetectShell crt_shell

#Trap CTRL-C, CTRL-Z:
trap 'trap1' INT
trap 'trap1' TSTP

err="false"
ls -1 "/dev/null">/dev/null 2>/dev/null || {
    printf "\n$E: \"ls -1\" (list one file per line) is needed in order for this program to function correctly!\n\n"
    err="true"
}

printf "test"|sort -n>/dev/null 2>/dev/null || {
    printf "\n$E: \"sort -n\" (numeric sort) is needed in order for this program to function correctly!\n\n"
    err="true"
}

if [ "$err" = "true" ]; then
    CleanUp && exit 1
fi

#Get the program parameters into the array "params":
count=0
for i; do
    count=$((count+1))
    eval params_$count=\"\$i\"
done
params_0=$((count))

if [ "$params_0" = "0" ]; then #if no parameters are provided: display help
    DisplayHelp
    CleanUp && exit 0
fi


#Create a flags array. A flag denotes special parameters:
help_flag="0"
install_flag="0"
file_flag="0"
directory_flag="0"
preview_flag="0"
i=1;
j=0;
while [ "$i" -le "$((params_0))" ]; do
    eval params_i=\"\$\{params_$i\}\"
    case "${params_i}" in
    "--help" | "-h" )
        help_flag="1"
    ;;
    "--install" | "-i" )
        install_flag="1"
    ;;
    "--file" | "-f" )
        file_flag="1"
    ;;
    "--dir" | "-d" )
        directory_flag="1"
    ;;
    "--preview" | "-p" )
        preview_flag="1"
    ;;

    * )
        j=$((j+1))
        eval selected_params_$j=\"\$params_i\"
    ;;
    esac

    i=$((i+1))
done

selected_params_0=$j
#Rebuild params array:
DestroyArray params
for i in $(seq 1 $selected_params_0); do
    eval params_$i=\"\$\{selected_params_$i\}\"
done
params_0=$selected_params_0

if [ "$help_flag" = "1" ]; then
    DisplayHelp
elif [ "$install_flag" = "1" ]; then

    file_path="$0"
    file_name_plus_ext="${file_path##*/}"
    file_dir_path="${file_path%/*}"
    file_name="${file_name_plus_ext%.*}"
    link_name="$file_name"
    install_path="$file_dir_path"

    #Install script (doesn't require root):
    {
        cd "$install_path"
    } && {
        ln -sfn "$file_name_plus_ext" "$link_name" #Create the link (or override/update it)
    } && {
        chmod u+x "$link_name" #Make the link 'executable' (+x) for the current user (u)"
    } && {
        printf '%s\n' "If not done already, please update the PATH variable (for the current user) by adding the next line to the end of \"~/.bashrc\" file or \"~/.zshrc\" (depending on the shell used) file:"
        printf '\n%s\n\n' "export PATH=\"\$PATH:\"'$install_path' #This is for updating the PATH variable"
        printf "and then close and reopen the terminal, in order for the new PATH to be loaded.\n"
    }||{
        printf '\n%s\n\n' "Could not install to the location: \"$install_path\"!"
        CleanUp && exit 1
    }
else
    #RUN PROGRAM

    PrintJustInTitle "A: Initialising, please wait..."


    if [ "$directory_flag" = "1" ]; then
        if [ ! "$file_flag" = "1" ]; then
            dir="-d"; file="-d"
        else
            dir="-d"; file="-f"
        fi
    else
        dir="-f"; file="-f" #(default)
    fi

    err="false"

    #Detect paths, conditions and parameters that are not paths or conditions:

    i=3; #count - jump over <mask1> and <mask2>
    p=0; #number of parameters that are paths
    c=0; #number of parameters that are conditions
    n=0; #number of parameters that are not paths or conditions

    extra_cond="\$i -eq \$i" #this condition is used to test if "$i" is a number or not
    one_cond="1 -eq 1" #default value in case one_cond is not set further

    while [ "$i" -le "$params_0" ]; do
        eval params_i=\"\$params_$i\"
        GetCharsArray params_i params_i_chars_array

        first_char="$params_i_chars_array_1"
        eval last_char=\"\$params_i_chars_array_$params_i_chars_array_0\"

        if [ "$first_char" = "{" -a "$last_char" = "}" ]; then
            c=$((c+1))
            one_cond="${params_i#?}" #? = Remove "{" prefix:
            one_cond="${one_cond%?}" # %? = Remove "}" suffix:
            GetCharsArray one_cond one_cond_chars_array
            j=1
            new_one_cond="" #new_one_cond should contain i replaced with $i
            while [ "$j" -le "$one_cond_chars_array_0" ]; do
                eval crt_char=\"\$one_cond_chars_array_$j\"
                if [ "$crt_char" = "i" ]; then
                    new_one_cond="$new_one_cond""\$i"
                else
                    new_one_cond="$new_one_cond""$crt_char"
                fi
                j=$((j+1))
            done
            one_cond="$new_one_cond"
        elif [ \( "$params_i" = "." -o "$params_i_chars_array_1$params_i_chars_array_2" = "./" -o "$params_i_chars_array_1$params_i_chars_array_2$params_i_chars_array_3" = "../" -o "$params_i_chars_array_1" = "/" \) ]; then #if a path is detected
            p=$((p+1))
            one_path="$params_i"
        else
            n=$((n+1))
        fi
        i=$((i+1))
    done

    set +f #enable globbing

    mask1="$params_1"
    mask2="$params_2"
    directory="$one_path"

    printf 'mask1="%s"\n' "$mask1"
    printf 'mask2="%s"\n' "$mask2"
    printf 'directory="%s"\n' "$directory"
    if [ ! "$c" = "0" ]; then
        printf '%s\n' "Condition = $one_cond"
    fi
    printf "\n"

    err=false

    if [ "$mask1" = "" ]; then
        printf "$E: <mask1> must not be empty!\n"
        err=true
    fi

    if [ "$mask2" = "" ]; then
        printf "$E: <mask2> must not be empty!\n"
        err=true
    fi

    #mask1 must contain a "@" character = number wildcard:
    first_rem_part="${mask1#*"@"}"
    if [ ! "$first_rem_part" = "${mask1}" ]; then #mask1 contains @
        second_rem_part="${first_rem_part#*"@"}"
        if [ ! "$second_rem_part" = "${first_rem_part}" ]; then #mask1 contains two @
            printf "$E: <mask1> must contain exactly one @ wildcard!\n"
            err=true
        fi
    else #mask1 does not contain @
        printf "$E: <mask1> must contain the @ wildcard!\n"
        err=true
    fi

    if [ "$directory" = "" ]; then
        printf "$E: <directory_path> must not be empty (must be \".\" or start with \"./\" or \"/\")!\n"
        err=true
    fi

    if [ -n "$mask1" -a "${mask1%%*"/"*}" = "" ]; then
        printf "$E: <mask1> must not contain directory sepparators ('/')!\n"
        err=true
    fi
    if [ -n "$mask2" -a "${mask2%%*"/"*}" = "" ]; then
        printf "$E: <mask2> must not contain directory sepparators ('/')!\n"
        err=true
    fi

    if [ "$n" -gt "0" ]; then
        printf "$E: Too many parameters: expected <mask1>, <mask2>, <directory_path> and eventually <condition>!\n"
        err="true"
    fi

    if [ "$p" -gt "1" ]; then
        printf "\n$E: Too many <directory_path> parameters provided: expected one after <mask1> and <mask2>!\n"
        err="true"
    fi

    if [ "$c" -gt "1" ]; then
        printf "\n$E: Too many <condition> parameters provided: expected one after <mask1> and <mask2>!\n"
        err="true"
    fi

    if [ "$err" = "true" ]; then
        printf "\n"
        CleanUp && exit 1
    fi

    rn_from_0=0
    #<mask1> contains exactly one @ wildcard

    #Generate pylon1 and pylon2 for mask1:
    pylon1_mask1="${mask1%%"@"*}"
    pylon2_mask1="${mask1#*"@"}"

    #Generate pylon1 and pylon2 for mask2:
    pylon1_mask2="${mask2%%"["*}"
    pylon2_mask2="${mask2##*"]"}"

    #Detect arithmetic expression:
    found_arith_expr="true"
    arith_expr="$mask2"
    if [ "${mask2#*"["}" = "$mask2" ]; then
        found_arith_expr="false"
    else
        arith_expr="${mask2#*"["}"
        if [ "${arith_expr%"]"*}" = "$arith_expr" ]; then
            found_arith_expr="false"
        else
            arith_expr="${arith_expr%"]"*}"
        fi
    fi
    if [ "$found_arith_expr" = "false" ]; then
        printf "\n$E: Expected at least one non-empty arithmetic expression ([...]) in <mask2>!\n\n"
        CleanUp && exit 1
    fi

    #Validate arithmetic expression (characters permitted are +, -, SPACE, TAB, (, ) and i ):
    GetCharsArray arith_expr arith_expr_chars_array
    #Count special characters in arithmetic expression:
    i=1;
    count=0;
    while [ "$i" -le "$arith_expr_chars_array_0" ]; do
        eval crt_char=\"\$arith_expr_chars_array_$i\"
        case "$crt_char" in
            [0-9] | " " | "\t" | "+" | "-" | "(" | ")" | "i" )
            count=$((count+1))
        ;;
        esac
        i=$((i+1))
    done
    if [ "$arith_expr_chars_array_0" -gt "$count" ]; then
        printf "\n$E: Characters not permited in arithmetic expression (the characters permitted are: +, -, SPACE, TAB, (, ) and i)!\n\n"
        CleanUp && exit 1
    fi

    #Check if the arithmetic expression has padding activated:
    #initially, assume no padding:
    arith_expr_padding="false"
    arith_expr_wo_padding="${arith_expr#"(0"*")"}"
    if [ -n "$arith_expr" ]; then
        if [ -n "$arith_expr_wo_padding" ]; then
            arith_expr_padding="${arith_expr%"$arith_expr_wo_padding"}"
            arith_expr_padding_number="${arith_expr_padding#"(0"}"
            arith_expr_padding_number="${arith_expr_padding_number%")"}"

            ValidateNaturalNumber arith_expr_padding_number result
            if [ "$result" = "true" ]; then
                #remove padding from the arithmetic expression:
                arith_expr="$arith_expr_wo_padding"
            else
                printf "\n$E: Invalid padding, in arithmetic expression!\n\n"
                CleanUp && exit 1
            fi
        else
            printf "\n$E: Number expected after padding, in arithmetic expression!\n\n"
            CleanUp && exit 1
        fi
    else
        printf "\n$E: Arithmetic expression must not be empty!\n\n"
        CleanUp && exit 1
    fi

    initial_dir="$PWD" #Store initial dir
    cd "$directory" 1>/dev/null 2>&1||{
        printf '\n%s\n\n' "$E: Cannot access directory: \"$directory\"!"
        CleanUp && exit 1
    }

    #Proceed to find matching file names and store them in numerically sorted order:
    #Check file names starting with "▄" (error):
    j=0
    k=0
    current_IFS="$IFS";
    IFS="
";
    err="false"
    for f in $(ls -1|sort -n); do

        j=$((j+1))

        PrintJustInTitle "A: Step 1 of 4 - checking file name ${j}..."

        if [ ! "$f" = "${f#"▄"}" ]; then #first char is "▄"
            printf '%s\n' "$E: The first character of \"$f\" is \"▄\" (probably remainings from a interrupted temporary rename)!"
            err="true"
        elif [ ! \( "$err" = "true" \) -a \( \( $file "$f" \) -o \( $dir "$f" \) \) ]; then
            case $f in
                *"$pylon1_mask1"*[0-9]*"$pylon2_mask1"* ) #$f is match for <mask1>

                    ProcedureGetMarginsAndNumber f

                    i=$number
                    eval [ \\\( $extra_cond \\\) -a \\\( $one_cond \\\) ] 2>/dev/null && {
                        #If <condition> is met:

                        #input file name = margin1 pylon1_mask1 number pylon2_mask1 margin2

                        k=$((k+1))

                        eval rn_from_$k=\"\$f\"
                        eval numbers_$k=\"\$number\"
                        eval margin1_$k=\"\$margin1\"
                        eval margin2_$k=\"\$margin2\"
                    }
                ;;
            esac
        fi
    done
    IFS="$current_IFS";
    eval rn_from_0=$((k))

    if [ "$err" = "true" ]; then
        printf "\n"
        CleanUp && exit 1
    fi

    if [ "$rn_from_0" = "0" ]; then
        printf "\nNo file names match the specified mask!\n\n"
        CleanUp && exit 0
    fi

    #Generate 'renamed to' file names:
    arith_err_encountered="false"
    for ii in $(seq 1 $rn_from_0); do

        PrintJustInTitle "A: Step 2 of 4: file name $ii of ${rn_from_0}..."

        #output file name = margin1 pylon1_mask2 arith_expr(number) pylon2_mask2 margin2

        eval new_f_n=\"\$margin1_$ii\$pylon1_mask2\"
        eval i=\"\$numbers_$ii\"; #should be ok becauses numbers are validated at mask1 matching; i is used in arithmetic expressions

        #Remove Zero's from the beginning of "i":
        sign=""
        if [ ! "${i#"-"}" = "$i" ]; then #i has a '-' sign
            sign="-"
        fi
        t="${i#"$sign""0"*[1-9]}"
        zeros="${i%"$t"}"
        zeros="${zeros%?}" #Remove last non-0 digit
        zeros="${zeros#"-"}" #Remove "-" sign
        i="$sign""${i#"$sign""$zeros"}"

        if [ "$crt_shell" = "dash" ]; then
            arith_expr_eval=$(($arith_expr)) || arith_err_encountered="true" #halts on error; catch error output
        else
            eval arith_expr_eval=\$\(\($arith_expr\)\) 2>/dev/null || arith_err_encountered="true" #does not halt on error; don't catch error output
        fi

        if [ "$arith_err_encountered" = "false" ]; then
            if [ ! "$arith_expr_padding" = "false" ]; then
                arith_expr_eval_padded="$(eval printf \"\%0$arith_expr_padding_number\d\" \"$arith_expr_eval\")"
                unset arith_expr_eval #zsh bug?
                arith_expr_eval="$arith_expr_eval_padded"
            fi
            new_f_n="$new_f_n$arith_expr_eval"
        else break; fi

        eval new_f_n=\"\$new_f_n\$pylon2_mask2\$margin2_$ii\"
        eval rn_to_$ii=\"\$new_f_n\"
    done
    rn_to_0=$rn_from_0

    if [ "$arith_err_encountered" = "true" ]; then
        printf "Arithmetic errors were encoutered: nothing done!\n\n"
        CleanUp && exit 1
    fi

    #Check if the arithmetic expression is constant:
    if [ ! "$rn_from_0" = "0" ]; then
        i=1
        number1=$(($arith_expr))
        i=2
        number2=$(($arith_expr))
        if [ "$number1" = "$number2" ]; then
            printf "$E: Constant arithmetic expression not allowed (=$number1)!\n\n"
            CleanUp && exit 1
        fi
    fi

    coll_err="false"

    ### Check for file name collision (1):
    coll_chk_1_markings_0=$rn_to_0
    PrintJustInTitle "A: Step 3 of 4: file name 1 of ${rn_to_0}..."
    if [ "$rn_to_0" -ge "2" ]; then
        prev_rn_from_fn="$rn_from_1"
        prev_rn_to_fn="$rn_to_1"
        fn_coll_detected="false"
        for ii in $(seq 2 $rn_to_0); do
            PrintJustInTitle "A: Step 3 of 4: file name $ii of ${rn_to_0}..."
            eval crt_rn_from_fn=\"\$rn_from_$ii\"
            eval crt_rn_to_fn=\"\$rn_to_$ii\"

            if [ "$prev_rn_to_fn" = "$crt_rn_to_fn" ]; then
                eval coll_chk_1_markings_$ii="1"
                eval coll_chk_1_markings_$((ii-1))="1"
                if [ "$fn_coll_detected" = "false" ]; then
                    printf '%s' "$E: File name collision: \"$prev_rn_from_fn\"; \"$crt_rn_from_fn\""
                    fn_coll_detected="true"
                    coll_err="true"
                else
                    printf '%s' "; \"$crt_rn_from_fn\""
                fi
            else
                if [ "$fn_coll_detected" = "true" ]; then
                    printf '%s\n' " -> \"$prev_rn_to_fn\""
                    fn_coll_detected="false"
                fi
            fi

            prev_rn_from_fn="$crt_rn_from_fn"
            prev_rn_to_fn="$crt_rn_to_fn"
        done
        #Treat last file separately:
        if [ "$fn_coll_detected" = "true" ]; then
            eval coll_chk_1_markings_$ii="1"
            printf '%s\n' " -> \"$crt_rn_to_fn\""
            fn_coll_detected="false"
        fi
    fi

    ### Check for temporary file name collision (2):
    temp_coll_detected="false"
    for j in $(seq 1 $rn_to_0); do
        PrintJustInTitle "A: Step 4 of 4: file name $j of ${rn_to_0}..."
        eval crt_rn_to_fn=\"\$rn_to_$j\"
        eval crt_rn_from_fn=\"\$rn_from_$j\"
        eval crt_coll_chk_1_marking=\"\$coll_chk_1_markings_$j\"
        if [ ! "$crt_coll_chk_1_marking" = "1" ]; then
            if [ -e "$crt_rn_to_fn" ]; then
                if [ \( $file "$crt_rn_to_fn" \) -o \( $dir "$crt_rn_to_fn" \) ]; then
                    case $crt_rn_to_fn in
                        *"$pylon1_mask1"*[0-9]*"$pylon2_mask1"* ) #file name is match for <mask1>

                            ProcedureGetMarginsAndNumber crt_rn_to_fn

                            i=$number
                            eval [ \\\( $extra_cond \\\) -a \\\( $one_cond \\\) ] 2>/dev/null && {
                                if [ ! "$temp_coll_detected" = "true" ]; then
                                    temp_coll_detected="true"
                                fi
                                eval marks_temp_fns_$j=\"\1\"
                            } || {
                                if [ ! "$coll_err" = "true" ]; then
                                    coll_err="true"
                                fi
                                eval marks_temp_fns_$j=\"\0\"
                                printf '%s\n' "$E: file name collision: $crt_rn_from_fn -> $crt_rn_to_fn"
                            }
                        ;;
                    esac
                else
                    if [ ! "$coll_err" = "true" ]; then
                        coll_err="true"
                    fi
                    printf '%s\n' "$E: file name collision: $crt_rn_from_fn -> $crt_rn_to_fn"
                fi
            else
                eval marks_temp_fns_$j=\"\0\"
            fi
        fi
    done

    if [ "$coll_err" = "true" ]; then
        if [ "$preview_flag" = "1" ]; then
            printf "\nPreview - File name collision errors were encoutered!\n\n"
        else
            printf "\nRename - File name collision errors were encoutered: nothing done!\n\n"
        fi
        CleanUp && exit 1
    fi

    #If no errors were encountered:

    if [ "$preview_flag" = "1" ]; then

        printf "Previewing rename:\n"
        for i in $(seq 1 $rn_from_0); do

            PrintJustInTitle "P: Step 1 of 1: file name $i of ${rn_from_0}..."

            eval crt_rn_from_fn=\"\$rn_from_$i\"
            eval crt_rn_to_fn=\"\$rn_to_$i\"
            printf '%s\n' "$crt_rn_from_fn -> $crt_rn_to_fn"
        done
    else
        printf "\n"
        err_encoutered="false"

        #Disable CTRL-C, CTRL-Z while the rename is in progress:
        trap '' INT
        trap '' TSTP

        printf "Rename in progress.. Please do not interrupt...\n">/dev/stdin

        if [ "$temp_coll_detected" = "false" ]; then
            for i in $(seq 1 $rn_from_0); do

                PrintJustInTitle "R: Step 1 of 1: file name $i of ${rn_from_0}..."

                eval crt_rn_from_fn=\"\$rn_from_$i\"
                eval crt_rn_to_fn=\"\$rn_to_$i\"
                {
                    mv -n "./$crt_rn_from_fn" "./$crt_rn_to_fn"
                }&&{
                    started_rn="true"
                }||{
                    printf '%s\n' "$E: RENAMING \"$crt_rn_from_fn\" TO \"$crt_rn_to_fn\"!"
                    err_encoutered="true"
                }
            done
        elif [ "$temp_coll_detected" = "true" ]; then

            for i in $(seq 1 $rn_from_0); do

                PrintJustInTitle "R: Step 1 of 3: file name $i of ${rn_from_0}..."

                eval crt_rn_from_fn=\"\$rn_from_$i\"
                eval crt_rn_to_fn=\"\$rn_to_$i\"
                eval crt_marks_temp_fn=\"\$marks_temp_fns_$i\"
                if [ "$crt_marks_temp_fn" = "0" ]; then

                    {
                        mv -n "./$crt_rn_from_fn" "./$crt_rn_to_fn"
                    }&&{
                        started_rn="true"
                    }||{
                        printf '%s\n' "$E: RENAMING \"$crt_rn_from_fn\" TO \"$crt_rn_to_fn\"!"
                        err_encoutered="true"
                    }
                fi
            done

            for i in $(seq 1 $rn_from_0); do

                PrintJustInTitle "R: Step 2 of 3: file name $i of ${rn_from_0}..."

                eval crt_rn_from_fn=\"\$rn_from_$i\"
                eval crt_rn_to_fn=\"\$rn_to_$i\"
                eval crt_marks_temp_fn=\"\$marks_temp_fns_$i\"
                if [ "$crt_marks_temp_fn" = "1" ]; then
                    if [ ! "$crt_rn_from_fn" = "$crt_rn_to_fn" ]; then #skip rename to itself cases
                        {
                            mv -n "./$crt_rn_from_fn" "./▄$crt_rn_to_fn"
                        }&&{
                            started_rn="true"
                        }||{
                            printf '%s\n' "$E: RENAMING \"$crt_rn_from_fn\" TO TEMPORARY FILE NAME \"▄$crt_rn_to_fn\"!"
                            err_encoutered="true"
                        }
                    fi
                fi
            done

            for i in $(seq 1 $rn_from_0); do

                PrintJustInTitle "R: Step 3 of 3: file name $i of ${rn_from_0}..."

                eval crt_rn_from_fn=\"\$rn_from_$i\"
                eval crt_rn_to_fn=\"\$rn_to_$i\"
                eval crt_marks_temp_fn=\"\$marks_temp_fns_$i\"
                if [ "$crt_marks_temp_fn" = "1" ]; then
                    if [ ! "$crt_rn_from_fn" = "$crt_rn_to_fn" ]; then #skip rename to itself cases
                        #started_rn is "true"
                        {
                            mv -n "./▄$crt_rn_to_fn" "./$crt_rn_to_fn"
                        }||{
                            printf '%s\n' "$E: RENAMING TEMPORARY FILE NAME \"▄$crt_rn_to_fn\" TO \"$crt_rn_to_fn\"!"
                            err_encoutered="true"
                        }
                    fi
                fi
            done
        fi

        printf "\n\nRename done.\n">/dev/stdin
    fi

    PrintJustInTitle "Done. Cleaning up..."

    CleanUp

fi
 
## MAIN END ##
1
11.03.2020, 22:00

Теги

Похожие вопросы