我有多个代表参与者的文件夹,每个文件夹都有一个名为con_0001.img。我想移动所有这些文件(con_0001.img)到一个新文件夹(而不是将它们放在各个参与者文件夹中)。
下面的代码似乎发现con_0001.img并将其移动到一个名为的新文件夹SA_A:
find . -name "con_0001.img" -exec mv '{}' "./SA_A/" ";"
然而,由于所有文件都被命名为con_0001.img
,我最终只有新文件夹中的一个文件(大概是因为所有后续文件都会相互覆盖)。
我确实设法找到了防止这种覆盖的建议,即:
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
但使用单个 shell 循环就更简单了:
for f in */con_0001.img; do
mv -- "$f" "./SA_A/${f%/*}_${f#*/}"
done