我知道我可以使用通配符在 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 确实不是将任何语法解释应用于扩展的上下文或括号之间的文本。为了避免与参数扩展发生冲突,字符串“${”不被视为符合括号扩展的条件。