
次のような名前の多くのファイルを含むサブディレクトリを含むディレクトリがあります:
file1.tif
file2.tif
file3.tif
file4.tif
file5.tif
file6.tif
file7.tif...
ファイル名に「サイクリング」サフィックスc1
、c2
、を追加して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
を使用してください。zsh
numericglobsort
答え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 氏のご協力と忍耐に改めて感謝いたします。