我有一堆这样的文件夹:
Team A - Folder 01/
Team A - Folder 02/
Team B - 14-12-2003 - Folder XX/
Team B - 21-03-2008 - Folder YY/
...
随着时间的推移,这个列表变得非常长且难以维护,所以我想将目录树更改为如下形式:
Team A/
Folder 01/
Folder 02/
Team B/
14-12-2003 - Folder XX/
21-03-2008 - Folder YY/
我知道我可以使用rename
正则表达式批量重命名文件,但它似乎无法像我想要实现的那样将内容重命名为子目录结构。
知道如何实现这个目标吗?
这是我使用的解决方案,灵感来自 Froggiz 提供的解决方案
#!/bin/bash
#Path with folders to move/rename
Path="/tmp/testmv/"
#Get each folder in original path
for ofolder in ${Path}/*;do
#replace space by _ to be able to use bash array
folder=${ofolder// /_}
#cut string to have only string after last /
folder=${folder##*/}
#create an array with _-_ as split delimiter (dash + 2 spaces around)
cutFoldArr=(${folder/_-_/ })
#create destination subfolder if not already exist
mkdir -p "${Path}${cutFoldArr[0]//_/ }"
#move original folder, to new sub folder destination
mv "${ofolder}" "${Path}${cutFoldArr[0]//_/ }/${cutFoldArr[1]//_/ }"
done
答案1
这是您想要的脚本,我只需要注意几件事:
- 实际上,代码在目标文件夹中创建子文件夹,但不移动文件,它仅显示它将要执行的操作,要执行移动,您需要取消注释“mv 行”(如果您不想要输出,可以注释掉 echo 行)
- 在 Linux 中,文件夹名称中带有空格不是一个好主意,因此我将空格改为下划线,因此如果您更喜欢空格
改变
${cutFoldArr[0]} & ${cutFoldArr[1]}
经过
${cutFoldArr[0]//_/ } & ${cutFoldArr[1]//_/ }
要调用此脚本,请将其放入 .sh 文件中,然后 bash YOURFILE.sh
#!bin/bash/
#原始文件夹的路径
fromPath="/opt/test/"
#目标路径
toPath="/opt/test2/"
#如果目标路径不存在,则创建目标路径
mkdir -p ${toPath}
#获取原始路径中的每个文件夹
对于 ${fromPath}/* 中的 ofolder;做
#用 _ 替换空格以便能够使用 bash 数组
文件夹=${ofolder// /_}
#剪切字符串,只保留最后一个 / 之后的字符串
文件夹=${文件夹##*/}
#创建一个数组-作为分割分隔符
cutFoldArr=(${文件夹/-/ })
#如果目标子文件夹不存在,则创建它
mkdir -p ${toPath}${cutFoldArr[0]}
#将原始文件夹移动到新的子文件夹目标
#mv ${ofolder} ${toPath}${cutFoldArr[0]}/${cutFoldArr[1]}
回显“mv ${ofolder} ${toPath} ${cutFoldArr[0]} / ${cutFoldArr[1]}”
完毕
抱歉,对于代码格式显示,我没有找到如何以更好的方式显示它。:P
有关特殊 bash 代码的更多信息:
$0 script name
${0##*/} = $(echo $0 | rev | cut -d/ -f1 | rev) allstring after last /
${0%/*} = $(echo $0 | sed "s/\/$Path//g") all string before last /
${0#*/}" delete all before first /
${0%/*}" delete all after /
${1%?} remove last char
${0:0:1} first char
${0/a/b} replace first a by b
${0//a/b} replace all a by b
(${0//@/ }) split char @
${0//[[:alpha:]]/X} replace alpha by X (can be [[:digit:]])
${0//[a-zA-Z]/X} and it works with reg exp
${0^^} to uppercase
${0,,} to lowercase
${#0} string size
${!var} create a dynamic variable
0 可以用你的变量名来改变
答案2
如果您的目录结构一致,您可以使用 Bash 的轻松编写脚本Remove matching pattern
。
来自 Bash 手册页:
${参数#单词} ${参数##单词}
删除匹配的前缀模式。单词被扩展以产生一个模式,就像在路径名扩展中一样。如果模式与参数值的开头匹配,则扩展的结果为参数的扩展值,其中删除了最短的匹配模式(# 情况)或最长的匹配模式(``##'' 情况)。如果参数是 @ 或 *,则模式删除操作将依次应用于每个位置参数,扩展为结果列表。如果参数是一个以 @ 或 * 为下标的数组变量,则模式删除操作将依次应用于数组的每个成员,扩展为结果列表。
给出您的示例,如果目录 Team A - Folder 01 是$dir
变量,echo ${dir#Team\ 01\ -\ }
则将其更改为Folder 01
等。