引用文件名中的通配符

引用文件名中的通配符

我知道我可以使用通配符在 bash 中使用星号提取具有特定格式名称的文件,如下所示:

$ ls
a01     a02     a03     a04     a05     a06     a07     a08     a09     b01     b02     b03     b04     b05     b06     b07     b08     b09
$ ls a*
a01     a02     a03     a04     a05     a06     a07     a08     a09
$ ls b*
b01     b02     b03     b04     b05     b06     b07     b08     b09

但是,如果我想将所有以 a 开头的文件移动到名为 的目录中 a,并将所有以 b 开头的文件移动到名为 的目录中b,我该如何使用一个命令来完成这些操作?

你能做这样的事吗:

$ mv *0* */

但是以某种方式引用了 move-to 参数中的第一个星号?

答案1

一个命令,一行:

for n in *;do [ -f "$n" ] && case "$n" in a*) mv "$n" a/;; b*) mv "$n" b/;; esac; done

或者,您可以从文件名中得出目录的名称,但我最初没有显示这一点,估计它会是一行较长的代码。例如,循环中的语句将是(第一次尝试):

d=$(echo "$n" | sed -e 's/^\(.\).*/\1/'); [ -f "$n" ] && mv "$n" $d/

将使用给定文件名的首字母来获取目录名。与

[ -f "$n" ] && case "$n" in a*) mv "$n" a/;; *b) mv "$n" b/;; esac

对于 case 语句。实际上不会太长,但很难即时输入。因为bash提到了,所以可以使用其子字符串语法${parameter:offset:length}来缩短该行:

d=${n:0:1}; [ -f "$n" ] && mv "$n" $d/

或者

[ -f "$n" ] && mv "$n" ${n:0:1}/

(我记得这是一个 bash 扩展,但在POSIX)。

关于重复使用通配符的实际问题:这显然是指括号扩展。它们在你需要它们之前就被展开了。引用文档:

执行括号扩展任何其他扩展,以及任何对其他扩展特殊的字符都会保留在结果中。它是严格文本. Bash 确实不是将任何语法解释应用于扩展的上下文或括号之间的文本。为了避免与参数扩展发生冲突,字符串“${”不被视为符合括号扩展的条件。

相关内容