「ケースの重複」バッチの名前を変更する

「ケースの重複」バッチの名前を変更する

この質問と回答について:https://unix.stackexchange.com/a/188020/189709

for f in *; do mv --backup=numbered -- "$f" "${f,,}"; done
rename -v -- 's/\.~(\d+)~/$1/' *.~*~

mv:このコマンドは、すべてのファイル名を暗黙的に小文字に変更します。これを行わないようにオプションを変更するにはどうすればよいですか?バックアップ番号はファイルを区別するのに十分です。

名前変更: test.~1~ test1 ファイルがすでに存在する場合、名前は変更されません。 test.~1~の名前をtest2に変更するオプションをどのように変更しますか?

答え1

mv表示されているコードは、実際のファイル名の競合時に重複するエントリをキャッチするために、呼び出し時にファイル名を明示的に小文字で指定するため、名前変更ポリシーを直接実装することをお勧めします。

以下は、実際に競合を引き起こさず、競合がある場合にのみファイル名を変更します(つまり、競合を処理するためにGNUに戻ることはありませんmv)。

#!/bin/bash

# The suffix array contains a filename suffix (a positive integer)
# for each lower-cased filename.
declare -A suffix

# Get all names in the current directory.
set -- *

# Initialise the suffixes for each existing name to zero.
for name do
        suffix[${name,,}]=0
done

for name do

        # Loop until no name collision.
        while true; do
                # Get the current suffix for this filename.
                suf=${suffix[${name,,}]}

                # Increment the suffix for this filename.
                suffix[${name,,}]=$(( ${suffix[${name,,}]} + 1 ))

                # If the suffix is 0, empty it.
                [[ $suf == 0 ]] && suf=

                # Create the new name.
                newname=$name$suf

                # Break out of the loop if the name didn't change, or if
                # there's no other file that has this name.
                if [[ $name == "$newname" ]] ||
                   [[ -z ${suffix[${newname,,}]} ]]
                then
                        break
                fi
        done

        if [[ $name != "$newname" ]]; then
                printf '%s --> %s\n' "$name" "$newname"
                # uncomment the next line to actually do the renaming
                # mv -- "$name" "$newname"
        else
                printf '%s unchanged\n' "$name"
        fi

done

(注釈付きの部分を参照してくださいmv。正しい操作を実行することが確実になるまで、その行を注釈付きの状態で実行することをお勧めします。)

テスト:

$ ls
A         Bb        TEST1     a         bb        test
BB        TEST      Test      bB        script.sh
$ bash script.sh
A unchanged
BB unchanged
Bb --> Bb1
TEST unchanged
TEST1 unchanged
Test --> Test2
a --> a1
bB --> bB2
bb --> bb3
script.sh unchanged
test --> test3

関連情報