1

ディレクトリとファイルの名前が間違っているディレクトリ構造があり、名前を修正する必要があります。ディレクトリにはサブディレクトリがあり、それらのサブディレクトリにはファイルのみがあります。

このツリー内で、次の表に従って名前を変更したファイルとサブディレクトリが必要です。たとえば、 という名前のディレクトリは に名前hdmを変更する必要がありますhdu。という名前のファイルは、以下の変換表に従って名前hdm_e_01.pngを変更する必要があります。hdu_e_01.png

ただし、これは 2 つのフェーズで行う必要があることに注意してください。これは、表に従ってhdu名前を変更する必要がある名前のディレクトリが既に存在するためです。したがって、フェーズ 1 ではすべての名前を競合しない一時的な名前に変更し、2 番目のフェーズでは最終的な名前に変更する必要があります。hdshduhduhds

From To
hda hdx
hde hdw
hdi hdv
hdm hdu
hdq hdt
hdu hds
hdb hdr
hdf hdq
hdj hdp
hdn hdo
hdr hdn
hdv hdm
hdc hdl
hdg hdk
hdk hdj
hdo hdi
hds hdh
hdw hdg
hdd hdf
hdh hde
hdl hdd
hdp hdc
hdt hdb
hdx hda
4

2 に答える 2

0

面白い問題を出してくれてありがとう。これが私の解決策です。

#!/bin/bash

TABLE_FILE='file.table'
DIRECTORY='.'
PRETEND=true  ## Set to false to change files.

declare -A RMAP=() FLAGS=() RENAMED=() NEWPATHS=()
declare -a ORDER=()

function check_directory {
    if [[ ! -d $DIRECTORY ]]; then
        echo "Directory does not exist: $DIRECTORY"
        return 1
    fi
    return 0
}

function parse_table_file {
    local -A F=() T=()
    local -i I=0

    if [[ ! -f $TABLE_FILE || ! -r $TABLE_FILE ]]; then
        echo "Table file does not exist or is not readable: $TABLE_FILE"
        return 1
    fi

    while read FROM TO; do
        if [[ -n ${F[FROM]} ]]; then
            echo "We can't have two the same sources: $FROM"
            return 1
        fi

        if [[ -n ${T[TO]} ]]; then
            echo "We can't have two them same replacements: $TO"
            return 1
        fi

        RMAP[$FROM]=$TO ORDER[I++]=$FROM F[$FROM]=. T[$TO]=.
    done < "$TABLE_FILE"
    return 0
}

function rename {
    local FROM=$1 TO=$2

    if [[ ${FLAGS[$FROM]} != R ]]; then
        if [[ ${FLAGS[$TO]} == H ]]; then
            echo "Circular rename point detected: $FROM - $TO"
            return 1
        elif [[ -n ${RMAP[$TO]} ]]; then
            FLAGS[$FROM]=H
            rename "$TO" "${RMAP[$TO]}" || return 1
        fi

        local -a TARGETS=("$DIRECTORY/$FROM"*)
        local NEWNAME NEWPATH

        for TARGET in "${TARGETS[@]}"; do
            NEWNAME=${TO}${TARGET##**"/${FROM}"}
            NEWPATH=${DIRECTORY}/${NEWNAME}

            echo "Renaming $TARGET to $NEWNAME ($NEWPATH)."

            if [[ -n ${NEWPATHS[$NEWPATH]} ]]; then
                echo "$TO has had same file matches as the previous ones: $NEWPATH through pattern ${NEWPATHS[$NEWPATH]}."
                return 1
            fi

            if [[ -e $NEWPATH ]]; then
                if [[ -n ${RENAMED[$NEWPATH]} ]]; then
                    if [[ $PRETEND == false ]]; then
                        echo "Can't rename $TARGET to $NEWNAME ($NEWPATH): file still exists and should have been renamed already with previous set ${RENAMED[$NEWPATH]}."
                        return 1
                    fi
                else
                    echo "Can't rename $TARGET to $NEWNAME ($NEWPATH): file already exists and is not part of the renaming sequence."
                    return 1
                fi
            fi

            if [[ $PRETEND == false ]]; then
                mv "$TARGET" "$NEWPATH" || {
                    echo "Failed to rename $NEWNAME to $NEWPATH."
                    return 1
                }
            fi

            NEWPATHS[$NEWPATH]=$TO
            RENAMED[$TARGET]="$FROM - $TO"
        done

        FLAGS[$FROM]=R
    fi

    return 0
}

function process {
    for FROM in "${ORDER[@]}"; do
        rename "$FROM" "${RMAP[$FROM]}" || return 1
    done
    return 0
}

check_directory && parse_table_file && process

このスクリプトは、一時的な名前変更を必要とせずに競合を解決および検出するために再帰を利用します。また、名前を変更したふりをして、変更が既に行われている場合にどうなるかを確認し、間違いを防ぐこともできます。

例私はこれらのファイルを持っていました:

aaa (D)
aab (D)
aaa.txt (F)

次に、テーブルに次の行がありました。

aaa aab
aab aac

これは私の出力です:

Renaming ./aab to aac (./aac).
Renaming ./aaa to aab (./aab).
Renaming ./aaa.txt to aab.txt (./aab.txt).
于 2013-09-12T11:15:53.967 に答える