Answers:
干得好:
for file in /home/user/temps/*/thumb.png; do new_file=${file/temps/new_folder}; cp "$file" "${new_file/\/thumb/}"; done;
编辑:
顺便说一句,规范的智慧是,为此使用find
一个坏主意-仅使用shell扩展更加可靠。另外,这是假设bash
,但我认为这是一个安全的假设:)
编辑2:
为了清楚起见,我将其分解:
# shell-expansion to loop specified files
for file in /home/user/temps/*/thumb.png; do
# replace 'temps' with 'new_folder' in the path
# '/home/temps/abc/thumb.png' becomes '/home/new_folder/abc/thumb.png'
new_file=${file/temps/new_folder};
# drop '/thumb' from the path
# '/home/new_folder/abc/thumb.png' becomes '/home/new_folder/abc.png'
cp "$file" "${new_file/\/thumb/}";
done;
有关该${var/Pattern/Replacement}
结构的详细信息,请参见此处。
该cp
行中的引号对于处理文件名中的空格和换行符等非常重要。
new_file/\/thumb
?
${VARIABLE/PATTTERN/REPLACEMENT}
产生值,VARIABLE
但模式由替换文本替换。这里的模式是/thumb
(/
需要进行转义,使其看起来不像${new_file//PATTERN/REPLACEMENT}
,这使其成为全局替换而不是首次出现的替换),并且替换文本为空。
这适用于任意深度的子目录:
$ find temps/ -name "thumb.png" | while IFS= read -r NAME; do cp -v "$NAME" "separate/${NAME//\//_}"; done
`temps/thumb.png' -> `separate/temps_thumb.png'
`temps/dir3/thumb.png' -> `separate/temps_dir3_thumb.png'
`temps/dir3/dir31/thumb.png' -> `separate/temps_dir3_dir31_thumb.png'
`temps/dir3/dir32/thumb.png' -> `separate/temps_dir3_dir32_thumb.png'
`temps/dir1/thumb.png' -> `separate/temps_dir1_thumb.png'
`temps/dir2/thumb.png' -> `separate/temps_dir2_thumb.png'
`temps/dir2/dir21/thumb.png' -> `separate/temps_dir2_dir21_thumb.png'
有趣的是参数扩展 ${NAME//\//_}
。它采用的内容NAME
,并用替换每次出现/
的_
。
注意:结果取决于工作目录和用于查找的path参数。我从临时目录的父目录执行了命令。替换cp
为echo
进行实验。
尝试这个
mkdir /home/user/thumbs
targDir=/home/user/thumbs
cd /home/user/temps
find . -type d |
while IFS="" read -r dir ; do
if [[ -f "${dir}"/thumb.png ]] ; then
echo mv -i "${dir}/thumb.png" "${targDir}/${dir}_thumb.png"
fi
done
编辑
我添加了引号,以防您的任何目录名中都嵌入了空格字符。
我也改变了它,所以它只会打印出要执行的命令。检查脚本的输出,以确保所有文件/路径名看起来正确。如果确定要执行的命令没有问题,请删除echo
。
mv -i ./A A/thumb.png ../tmp/.png
-所有文件都以../tmp/.png结尾(../tmp是我的目标目录)。
find -type d
并查看输出。这样可以得到您期望的所有目录吗?如果没有,请添加一些输出以显示问题。祝好运。
read dir
执行分词,并从目录a\nb
a和b中将其作为两个实例,而掩蔽无法解决。