「サイクリング」サフィックスを追加してファイル名を変更する

「サイクリング」サフィックスを追加してファイル名を変更する

次のような名前の多くのファイルを含むサブディレクトリを含むディレクトリがあります:

file1.tif
file2.tif
file3.tif
file4.tif
file5.tif
file6.tif
file7.tif...

ファイル名に「サイクリング」サフィックスc1c2、を追加してc3、次のファイル名を取得します。

file1c1.tif
file2c2.tif
file3c3.tif
file4c1.tif
file5c2.tif
file6c3.tif
file7c1.tif...

これはトップディレクトリのすべてのサブディレクトリに当てはまります。

しかし、どうすればそれができるのか分かりません。

それは可能ですか?どうやって?

答え1

find+ Perlベースprename(つまり以前のUbuntu)ではrename、リテラルの前の数字のシーケンスを一致させて.から、剰余除算を使用して目的の形式で書き込むことができます。例:

find . -name '*.tif' -execdir prename -vn -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +

(フラグを-vn使用すると、コミットする前にファイルの名前がどのように変更されるかを確認するための「ドライ ラン」を実行できます)。


例:与えられた

$ tree
.
├── bar
│   ├── file1.tif
│   ├── file2.tif
│   ├── file3.tif
│   ├── file4.tif
│   ├── file5.tif
│   ├── file6.tif
│   └── file7.tif
├── foo
│   ├── egg
│   │   ├── file1.tif
│   │   └── file2.tif
│   ├── file1.tif
│   ├── file2.tif
│   └── file3.tif
└── spam
    ├── file1.tif
    └── file2.tif

4 directories, 14 files

それから

find . -name '*.tif' -execdir prename -- 's/(\d+)\./sprintf "%dc%d.", $1, ($1-1)%3+1/e' {} +

結果的に

$ tree
.
├── bar
│   ├── file1c1.tif
│   ├── file2c2.tif
│   ├── file3c3.tif
│   ├── file4c1.tif
│   ├── file5c2.tif
│   ├── file6c3.tif
│   └── file7c1.tif
├── foo
│   ├── egg
│   │   ├── file1c1.tif
│   │   └── file2c2.tif
│   ├── file1c1.tif
│   ├── file2c2.tif
│   └── file3c3.tif
└── spam
    ├── file1c1.tif
    └── file2c2.tif

4 directories, 14 files

答え2

コメントに基づいて編集:

カウンターを循環させたい場合、つまり 1 から 3 の間を循環させたい<number>場合:c<number>

予行演習:

shopt -s globstar
for d in **/*/; do 
    ( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do 
        echo mv -i "$f" "${f%.tif}"c${count}.tif
        if ((count=3)); then 
            count=1
        else
            ((count++))
        fi
     done ) 
done

アクション:

shopt -s globstar
for d in **/*/; do 
    ( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do 
        mv -i "$f" "${f%.tif}"c${count}.tif
        if ((count=3)); then 
            count=1
        else
            ((count++))
        fi
     done ) 
done

例:

$ tree
.
├── bar
│   ├── file1.tif
│   ├── file2.tif
│   ├── file3.tif
│   └── file4.tif
├── foo
│   ├── egg
│   │   ├── file1.tif
│   │   └── file2.tif
│   ├── file1.tif
│   ├── file2.tif
│   └── file3.tif
└── spam
    ├── file1.tif
    └── file2.tif

$ shopt -s globstar
$ for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob && for f in file*.tif; do \
    echo mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done
/home/foobar/bar
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
mv -i file4.tif file4c1.tif
/home/foobar/foo
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
mv -i file3.tif file3c3.tif
/home/foobar/foo/egg
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif
/home/foobar/spam
mv -i file1.tif file1c1.tif
mv -i file2.tif file2c2.tif

$ for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && for f in file*.tif; do \
    mv -i "$f" "${f%.tif}"c${count}.tif; if ((count=3)); then count=1; else ((count++)); fi; done ); done

$ tree
.
├── bar
│   ├── file1c1.tif
│   ├── file2c2.tif
│   ├── file3c3.tif
│   └── file4c1.tif
├── foo
│   ├── egg
│   │   ├── file1c1.tif
│   │   └── file2c2.tif
│   ├── file1c1.tif
│   ├── file2c2.tif
│   └── file3c3.tif
└── spam
    ├── file1c1.tif
    └── file2c2.tif

元の回答:

bash

shopt -s globstar
for d in **/*/; do ( cd "$d" && pwd && count=1 && shopt -s nullglob \
    && for f in file*.tif; do echo mv -i "$f" "${f%.tif}"c${count}.tif; \
        ((count++)); done ); done
  • ここではディレクトリ名をループしています。globstarシェルオプションを使用すると、ディレクトリを再帰的に走査できます。

  • 内部の部分は()サブシェルで実行されます。これは、cd現在のシェルで変更されるのを防ぐためです。

  • cdディレクトリに - してファイルを探し、file*.tif必要に応じて名前を変更します

  • count名前を変更する間、各ファイルごとに増加するカウンタ を保持する


上記はドライランであり、名前の変更が行われるディレクトリとmv実行されるコマンドが表示されます。問題がなければ、次の操作を実行します。

shopt -s globstar
for d in **/*/; do ( cd "$d" && count=1 && shopt -s nullglob && \
  for f in file*.tif; do mv -i "$f" "${f%.tif}"c${count}.tif; ((count++)); done ); done

注意点として、シェルは字句によるソートを行うため、たとえばファイルはfile10.tifよりも前に名前が変更されます。これを望まない場合は、名前を変更する前に何らかのソートを行うか、 withオプションfile2.tifを使用してください。zshnumericglobsort

答え3

heemayl のおかげで、すべてが解決しました。指示されたサイクル増分ループは、私たちの手ではうまく機能しなかったため、少し修正する必要がありました。変更したのは、次のコードです: if ((count=3)) を、次のコードに: if (("$count"==3)) 最終的に、現在正常に使用できるコードは次のとおりです:

    shopt -s globstar
for d in **/*/; do 
    ( cd "$d" && count=1 && shopt -s nullglob && for f in *.tif; do 
       echo mv -i "$f" "${f%.tif}"c${count}.tif

if (("$count"==3)); then 
count=1
        else 
((count++))
        fi
     done ) 
done

heemayl 氏のご協力と忍耐に改めて感謝いたします。

関連情報