参加者を表す複数のフォルダがあります。各フォルダにcon_0001.img。このすべてのファイルを移動したいです(con_0001.img)を新しいフォルダにコピーします(個々の参加者フォルダに配置する代わりに)。
以下のコードは次のように見えます。con_0001.imgという名前の新しいフォルダに移動します。SA_A:
find . -name "con_0001.img" -exec mv '{}' "./SA_A/" ";"
ただし、すべてのファイルの名前があるため、con_0001.img
新しいフォルダには1つのファイルしか残りません(おそらくそれ以降のすべてのファイルが互いに上書きされるため)。
私はこのオーバーライドを防ぐための提案を見つけました。つまり:
find . -name "con_0001.img" -exec mv --backup=numbered "{}" "./SA_A/" \;
しかし、最終的にファイルができました。con_0001.img複数のフォルダから消えて上書きされたようです。mv
に変更すると、cp
ファイルも作成されます(ただし、ファイルをコピーして期待どおりにファイルはそのまま残ります)。
上書きを防ぐ方法はありますか?もちろん、ファイルを新しいフォルダに移動するときに親ディレクトリ名(参加者番号)の一部をファイルに追加する方法はありますか?たとえば、
p102/con_0001.img ----> p102_con_0001.img
p105/con_0001.img ----> p105_con_0001.img
移動したファイルに親ディレクトリを追加する必要があるように、次のコードを適用してみました。
find . -name 'con_0001.img' | while read filePath; do cp "$filePath" './SA_A'/"$(echo "$filePath")"; done
ただし、エラーが返されます。
一般ファイル '/SA_A/./p105/con_0001.img' を生成できません。そのファイルやディレクトリはありません。
新しいフォルダ以降に予期しない期間があるようです。/SA_A/。これがコードが機能しない理由ですか?この期間はどこから来ましたか?
ベストアンサー1
mkdir SA_A
find . -name "con_0001.img" -exec sh -c '
for f; do d=${f%/*}; mv -- "$f" "./SA_A/${d#./}${f##*/}"; done
' findsh {} +
forループは見つかった各ファイルを繰り返します。
d=${f%/*}
ファイルのデフォルト名である一番右の/*
部分を削除します。f
${d#./}
./
ファイルの先頭部分を削除します。${f##*/}
ファイルのデフォルト名を取得し、最後のファイルを削除します/
。
実行前:
$ ls a1 a2 a3
a1:
con_0001.img
a2:
con_0001.img
a3:
con_0001.img
実行後:
$ ls a1 a2 a3 SA_A/
a1:
a2:
a3:
SA_A/:
a1con_0001.img a2con_0001.img a3con_0001.img
しかし、単一のシェルループを使用すると、はるかに簡単です。
for f in */con_0001.img; do
mv -- "$f" "./SA_A/${f%/*}_${f#*/}"
done