bash根据文件名将文件移动到子目录

时间:2018-07-30 15:12:17

标签: bash

我有这样命名的文件:

A-1230.pdf
A-2450.pdf
A-6780.pdf

B-1230.pdf
B-2450.pdf
B-6780.pdf

...和这样的目录结构:

A
- 000
- 001
-...
- 999

B
- 000
- 001
-...
- 999

否,我想将文件移动到其相应的子目录。意思

A-1230.pdf goes into A -> 123
B-2450.pdf goes into B -> 245

以此类推。

我用bash尝试了以下方法:

mv +([A-Z]-[0-9][0-9][0-9]*.pdf) $1/$2$3$4

但这不起作用。如何在bash中正确使用反向引用并捕获组?

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

bash对正则表达式的支持与[[ $string =~ $regex ]]一起使用,并将捕获组放置在数组BASH_REMATCH中。

for file in ?-*.pdf; do
  [[ $file =~ ([[:alpha:]])-([[:digit:]]{3}).* ]] || continue
  mkdir -p -- "${BASH_REMATCH[1]}/${BASH_REMATCH[2]}" || continue 
  mv -- "$file" "${BASH_REMATCH[1]}/${BASH_REMATCH[2]}/"
done

答案 1 :(得分:0)

您试图实现的是所谓的反向引用。不幸的是,球状表达式没有这样的概念。表达式,例如:

mv (*).pdf $1/
cp ([0-9])-(*).txt $2-$1.text

在任何shell(bash,zsh,ksh,csh)中根本不可能。

存在解决方法,方法是遍历每个文件并对其进行后期处理:

for file in [A-Z]-[0-9][0-9][0-9]*.pdf; do
   dir="${file:0:5}"; dir="${dir/-/\/}"
   mkdir -p "$dir"
   mv "$file" "$dir"
done

或更聪明,如Charles Duffy

ZSH为此任务开发了一套单独的工具(zcpzmvzln),这些工具可以进行反向引用。因此,您的任务可以按以下方式执行:

zmv -n '([A-Z])-([0-9][0-9][0-9])[0-9].pdf' '$1/$2/'

-n标志显示了将要执行的操作,但实际上并未执行该操作,因为它作为试运行。删除该标志以执行实际移动。

注意:ZSH没有针对球形表达式的反向引用。注意上面的zmv示例中使用的单引号。他们禁止滚球。 FROM和DEST部分是这些工具的自变量。该工具也未在任何$PATH中找到,因为它们是zsh系统的一部分。这与实际的二进制文件cpmvln不同。