複数のファイル名から日付の名前を変更する方法

複数のファイル名から日付の名前を変更する方法

私のファイルは次のとおりです。

ABC_20210101.csv
ABC_20210101_imp.csv

ファイル名の日付を特定の日付に更新したいと思います。

ABC_20201231.csv
ABC_20201231_imp.csv

これらのファイル名をどのように変更できますか?

答え1

GNU並列処理を使用する:

ls | parallel mv {} '{= s/(.*)\d{8}/${1}20210131/ =}'

テスト対象:

this_123456789_file_19991231_some.thing

ソフトウェアを実行するシステムにソフトウェアをインストールする権限がない場合は、スクリプトにGNU Parallelを直接含めることができます。

parallel --embed > newscript.sh

答え2

bashファイル名を分離して再結合することができます。

#!/bin/bash
new="20201231"

for file in *.csv
do
    # Split the filename into its consituent parts
    if [[ "$a" =~ (.*)[0-9]{8}(_imp)?(\.csv)$ ]]
    then
        # Assemble a new filename
        dest="${BASH_REMATCH[1]}${new}${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
        if [[ ! -f "$dest" ]]
        then
            # No destination so rename
            [[ -t 2 ]] && echo "Rename $file as $dest" >&2
            echo mv -f "$file" "$dest"    # Remove "echo" to action
        fi
    fi
done

これは簡単ですが、renameすべてのシステムにインストールされているわけではありません(削除したり、ジョブと-n交換)。-v

new="20201231" rename -n 's/(.*)?[0-9]{8}(_imp)?(\.csv)$/$1$ENV{new}$2$3/' *.csv

使用できない場合、bashまたは必要なターゲットファイル名を生成するために使用renameできます。確かに、これはコードを読みやすくします(ERE処理をsed満たすために多くのバックスラッシュエスケープを持つREを除く)。sed

new="20201231"

for file in *.csv
do
    # Generate new filename
    dest=$(
        printf "%s\n" "$file" |
        sed -n 's/\(.*\)[0-9]\{8\}\(_imp\)\{0,1\}\(\.csv\)$/\1---\2\3/p'
    )

    if [ -n "$dest" ] && [ ! -f "$dest" ]
    then
        # Pattern substitued and target does not exist so rename
        [[ -t 2 ]] && echo "Rename $file as $dest" >&2
        echo mv -f "$file" "$dest"    # Remove "echo" to action
    fi
done

答え3

ファイルの名前を変更する1つの方法は、最初にfindユーティリティabdを使用してファイルを選択し、それをsedに渡して新しい名前を設定し、tgenがxargsにペアを渡してmvコマンドを呼び出して名前を変更することです。

d0=19710110
d8=$(seq -f '[0-9%g]' 8 | paste -sd'\0')
find . -maxdepth 1 -type f \( -name "*_${d8}_imp.csv" -o -name "*_$d8.csv" \) -print |
sed -Ee "h;/_[0-9]{8}((_imp)?[.]csv)\$/s//_$d0\1/;x;G" |
xargs -r -d'\n' -n2 -t mv -i

答え4

標準のPOSIXshシェルを使用すると、次のパターンを作成できます。

./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv

そして

./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_imp.csv

これは現在のディレクトリ内の関心のあるファイルと一致します。 (もちろんこれをより具体的にすることができます。./*20[0-2][0-9][01][0-9][0-3][0-9].csvたとえば、無効な日付の一致も許可します。)その後、これらのパターンに一致する名前は次のように名前を変更できます。

for name in ./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv
do
    [ ! -e "$name" ] && continue
    newname=${name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].csv}20201231.csv
    mv "$name" "$newname"
done

for name in ./*[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_imp.csv
do
    [ ! -e "$name" ] && continue
    newname=${name%[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_imp.csv}20201231_imp.csv
    mv "$name" "$newname"
done

置換は、${variable%pattern}値の末尾から一致する文字列を削除します。pattern$variable

関連情報