bash - Bash / sh:移动文件夹+子文件夹隐蔽地重命名文件(如果存在)
问题描述
我正在尝试创建一个 bash 脚本,它将所有文件递归地从源文件夹移动到目标文件夹,并简单地重命名文件(如果它们已经存在)。与 M$ Windows 的方式类似,当文件存在时,它会使用"<filemame> (X).<ext>"
等自动重命名,但所有文件除外。
我已经创建了以下内容,它适用于几乎所有场景,除非文件夹的名称中有 (.) 句点并且该文件夹中的文件没有扩展名(名称中没有句点)。
例如文件夹路径文件,例如:"./oldfolder/this.folder/filenamewithoutextension"
我得到(错误地):
"./newfolder/this (1).folder/filenamewithoutextension"
如果"./newfolder/this.folder/filenamewithoutextension"
已存在于目标位置 ( ./newfolder
),
而不是正确命名新文件:"./oldfolder/this.folder/filenamewithoutextension (1)"
#!/bin/bash
source=$1 ; target=$2 ;
if [ "$source" != "" ] && [ "$target" != "" ] ; then
#recursive file search
find "$source" -type f -exec bash -c '
#setup variables
oldfile="$1" ; osource='"${source}"' ; otarget='"${target}"' ;
#set new target filename with target path
newfile="${oldfile/${osource}/${otarget}}" ;
#check if file already exists at target
[ -f "${newfile}" ] && {
#get the filename and fileextension for numbering - ISSUE HERE?
filename="${newfile%/}" ; newfileext="${newfile##*.}" ;
#compare filename and file extension for missing extension
if [ "$filename" == "$newfileext" ] ; then
#filename has no ext - perhaps fix the folder with a period issue here?
newfileext="" ;
else
newfileext=".$newfileext" ;
fi
#existing files counter
cnt=1 ; while [ -f "${newfile%.*} (${cnt})${newfileext}" ] ; do ((cnt+=1)); done
#set new filename with counter - New Name created here *** Needs re-work, as folder with a period = fail
newfile="${newfile%.*} (${cnt})${newfileext}";
}
#show mv command
echo "mv \"$oldfile\" \"${newfile}\""
' _ {} \;
else
echo "Requires source and target folders";
fi
我怀疑问题是,如何正确识别文件名和扩展名,在这一行中找到:
filename="${newfile%/}" ; newfileext="${newfile##*.}"
它不能正确识别文件名(文件总是在最后一个 / 之后)。
关于如何使其正常工作的任何建议?
更新:只是一些完成说明 - 问题修复:
- 最初拆分每个完整路径文件名:路径-文件名-(可选ext)
- 重构全路径文件名:路径-文件名-计数器-(可选ext)
- 修复了文件移动以确保使用 mkdir -p 存在目录结构(如果目标位置中不存在新文件夹,mv 不会创建新文件夹)。
解决方案
也许你可以试试这个?
filename="${newfile##*/}" ; newfileext="${filename#*.}"
- 第一个模式意味着:删除最长的前缀(以贪婪的方式)直到最后一个
/
. - 第二个:删除直到第一个点的前缀(这里似乎不需要贪婪模式) - 正如您已经注意到的,如果文件名不包含点,您将得到
newfileext == filename
......</li>
示例会话:
newfile='./oldfolder/this.folder/filenamewithoutextension'
filename="${newfile##*/}"; newfileext="${filename#*.}"
printf "%s\n" "$filename"
#→ filenamewithoutextension
printf "%s\n" "$newfileext"
#→ filenamewithoutextension
newfile='./oldfolder/this.folder/file.tar.gz'
filename="${newfile##*/}"; newfileext="${filename#*.}"
printf "%s\n" "$filename"
#→ file.tar.gz
printf "%s\n" "$newfileext"
#→ tar.gz
推荐阅读
- extjs - 仅过滤 extjs 组合框中的前 3 个字母
- arrays - 更改由 ngFor bucle 显示的图像的背景颜色
- python - 将应用程序从 python2.7 移植到 python3.7 后的字节字符串问题
- java - 线程“main”java.lang.Error 中的异常:未解决的编译问题:
- java - 如何在不更改 Set 顺序的情况下在字符串周围添加引号?
- vba - Strange Behavior: Variant Set to Object without using Set
- shell - How to run commands while logging from one machine to another using Expect
- javascript - 在 Chrome 中拖放重影图像位置错误
- python - 教模型使用布尔条目分析相同大小的数组和输出数组
- python - Python `schedule` 计划任务的返回值去哪了?