Bash 移动和重命名文件夹

Bash 移动和重命名文件夹

我有一堆这样的文件夹:

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等。

相关内容