![在 bash 中使用带有通配符的 mv 时如何动态创建目标目录结构?](https://linux22.com/image/1397519/%E5%9C%A8%20bash%20%E4%B8%AD%E4%BD%BF%E7%94%A8%E5%B8%A6%E6%9C%89%E9%80%9A%E9%85%8D%E7%AC%A6%E7%9A%84%20mv%20%E6%97%B6%E5%A6%82%E4%BD%95%E5%8A%A8%E6%80%81%E5%88%9B%E5%BB%BA%E7%9B%AE%E6%A0%87%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84%EF%BC%9F.png)
我对 BASH 脚本还很陌生,正在寻找一种优雅的方法来解决我的任务:
在给定目录中,某些文件通常需要分类到子文件夹中。文件的名称具有固定的结构,并且这些文件应放在哪个目标文件夹中取决于它们的名称。
目前我的脚本如下所示:
#!/bin/bash
declare -r SOURCEDIR=/some/dir/upload
declare -r DESTBASEDIR=/some/dir/archive
for year in "2009" "2010" "2011" "2012" "2013" "2014"; do
for letter in {0..9} {A..Z}; do
mkdir -p ${DESTBASEDIR}/${year}/${letter}
mv ${SOURCEDIR}/123456789012_${letter}?_??_${year}????.dat ${DESTBASEDIR}/${year}/${letter}/
done
done
该脚本完全符合我的要求,但即使 mv 找不到任何文件可以移动到目标文件夹,它也会创建目标文件夹。我希望 mv 有一个选项可以创建必要的目录,而不是使用 mkdir 创建它们。
我知道当不存在要移动的文件时,此脚本将显示错误。脚本完成后,我将隐藏错误消息。
是否有一种简单而优雅的方法可以动态创建目录结构而无需创建空目录?
感谢您的帮助!
问候
曼努埃尔
glenn jackman 的版本启发了我使用以下脚本来实现这个效果:)
#!/bin/bash
declare -r SOURCEDIR=/some/dir/upload
declare -r DESTBASEDIR=/some/dir/archive
cd "$SOURCEDIR"
for f in 1234567890_* ; do
letter=${f:11:1}
year=${f:21:4}
dest="$DESTBASEDIR/$year/$letter"
mkdir -p "$dest"
mv "$f" "$dest"
done
请注意,自从我发现文件名内的偏移量已经移动以来,文件名开头的前导数字更短了。给出的解决方案是根据我的错误示例设计的。
这种方法不太安全,因为它不检查源目录中文件的文件名是否按预期组成。在这种情况下,我可以依赖它,因此不验证这一点不会带来太大的风险。
Glenn Jackman 版本中的这句话
for f in 123456789012_[A-Z]?_??_[0-9][0-9][0-9][0-9]????.dat ; do
不起作用。在我的 bash 中,“in”后面的值被解释为文字字符串。我不知道如何“修复”这个问题。
答案1
这将只创建文件名中实际使用的年份/字母目录。
cd "$SOURCEDIR"
for f in 123456789012_[A-Z]?_??_[0-9][0-9][0-9][0-9]????.dat ; do
letter=${f:13:1}
year=${f:19:4}
dest="$DESTBASEDIR/$year/$letter"
mkdir -p "$dest"
mv "$f" "$dest"
done
请注意,如果变量的值包含空格,则使用${braces}
不同于使用"$quotes"