我如何 move/group bash 中的特定文件夹?
How can i move/group specific folders in bash?
我的文件夹结构如下:
2020-123-1
2020-123-2
2020-123-3
2020-124-1
2020-124-2
...
我需要根据前 2 个数字创建文件夹并省略第二个破折号 (-) 后面的内容。然后我需要将之前的文件夹以正确的名称放在新创建的文件夹下。
2020-123
->2020-123-1
->2020-123-2
->2020-123-3
2020-124
->2020-124-1
->2020-124-2
我试过在 bash 中编写这样的脚本:
ls -d */ > folder.txt
cut -f1,2 -d"-" folder.txt |cut -f1 -d"/" |sort|uniq > mainfolder.txt
while read line; do mkdir $line ; done < mainfolder.txt
while read line; do mv $(cut -f1,2 -d"-" $line) $line/ ; done < folder.txt
我无法使最后一行工作,我知道它有问题。
实际上,您不必解析目录名称并构建层次结构。您可以使用 mkdir
的 -p
选项,因此,一个 awk 一行就可以完成这项工作:
awk -F'-' '{top= FS ;printf "mkdir -p %s; mv %s %s\n",top, [=10=], top}' dir.txt
您的示例的输出:
mkdir -p 2020-123; mv 2020-123-1 2020-123
mkdir -p 2020-123; mv 2020-123-2 2020-123
mkdir -p 2020-123; mv 2020-123-3 2020-123
mkdir -p 2020-124; mv 2020-124-1 2020-124
mkdir -p 2020-124; mv 2020-124-2 2020-124
备注
- 这一行只打印命令而不执行它们,如果一切正常,您只需将输出通过管道传输到
|sh
。检查输出命令,更改printf
format/values 进行调整。
- 我没有引用文件名,因为您的示例不包含任何特殊字符。有的话就去做
所以最终的脚本如下:
ls -d */ | cut -f1 -d"/" > folder.txt
awk -F'-' '{top= FS ;printf "mkdir -p %s; mv %s %s\n",top, [=10=], top}' folder.txt |sh
纯bash:
#!/bin/bash
for src in *-*-*; do
destdir=${src%-*}
[[ -d $destdir ]] || mkdir "$destdir" || exit
# This just prints out the command that will be called.
# Remove the "echo" in actual script after making sure it will run as intented
echo mv "$src" "$destdir"
done
在上面的脚本中,假设要移动的每个文件名都恰好包含两个破折号。如果它可以包含两个 或更多 破折号,则 destdir=${src%-*}
行应替换为以下两行:
suffix=${src#*-*-}
destdir=${src%"-$suffix"}
有关详细信息,请阅读 "shell parameter expansion" section in bash reference。
此外,值得一读的文章是:Why you shouldn't parse the output of ls
我的文件夹结构如下:
2020-123-1
2020-123-2
2020-123-3
2020-124-1
2020-124-2
...
我需要根据前 2 个数字创建文件夹并省略第二个破折号 (-) 后面的内容。然后我需要将之前的文件夹以正确的名称放在新创建的文件夹下。
2020-123
->2020-123-1
->2020-123-2
->2020-123-3
2020-124
->2020-124-1
->2020-124-2
我试过在 bash 中编写这样的脚本:
ls -d */ > folder.txt
cut -f1,2 -d"-" folder.txt |cut -f1 -d"/" |sort|uniq > mainfolder.txt
while read line; do mkdir $line ; done < mainfolder.txt
while read line; do mv $(cut -f1,2 -d"-" $line) $line/ ; done < folder.txt
我无法使最后一行工作,我知道它有问题。
实际上,您不必解析目录名称并构建层次结构。您可以使用 mkdir
的 -p
选项,因此,一个 awk 一行就可以完成这项工作:
awk -F'-' '{top= FS ;printf "mkdir -p %s; mv %s %s\n",top, [=10=], top}' dir.txt
您的示例的输出:
mkdir -p 2020-123; mv 2020-123-1 2020-123
mkdir -p 2020-123; mv 2020-123-2 2020-123
mkdir -p 2020-123; mv 2020-123-3 2020-123
mkdir -p 2020-124; mv 2020-124-1 2020-124
mkdir -p 2020-124; mv 2020-124-2 2020-124
备注
- 这一行只打印命令而不执行它们,如果一切正常,您只需将输出通过管道传输到
|sh
。检查输出命令,更改printf
format/values 进行调整。 - 我没有引用文件名,因为您的示例不包含任何特殊字符。有的话就去做
所以最终的脚本如下:
ls -d */ | cut -f1 -d"/" > folder.txt
awk -F'-' '{top= FS ;printf "mkdir -p %s; mv %s %s\n",top, [=10=], top}' folder.txt |sh
纯bash:
#!/bin/bash
for src in *-*-*; do
destdir=${src%-*}
[[ -d $destdir ]] || mkdir "$destdir" || exit
# This just prints out the command that will be called.
# Remove the "echo" in actual script after making sure it will run as intented
echo mv "$src" "$destdir"
done
在上面的脚本中,假设要移动的每个文件名都恰好包含两个破折号。如果它可以包含两个 或更多 破折号,则 destdir=${src%-*}
行应替换为以下两行:
suffix=${src#*-*-}
destdir=${src%"-$suffix"}
有关详细信息,请阅读 "shell parameter expansion" section in bash reference。
此外,值得一读的文章是:Why you shouldn't parse the output of ls