2

我有一个关于为什么这不起作用的问题。可能,这是一个简单的答案,但我似乎无法弄清楚。

我想移动我拥有的几个文件。它们都具有相同的文件名(比如 file1),但它们都在不同的目录中(比如 /tmp/dir1、dir2 和 dir3)。如果我要单独移动这些,我可以按照以下方式做一些事情:

mv /tmp/dir1/file1 /tmp

这样可行。但是,我有多个目录,它们都将出现在同一个位置......而且我不想覆盖。所以,我尝试了这样的事情:

mv /tmp/{dir1,dir2,dir3}/file1 /tmp/file1.{a,b,c}

当我尝试这个时,我得到:

/tmp/file1.c 不是目录

只是为了澄清......这也有效:

mv /tmp/dir1/file1 /tmp/file1.c

很确定这与大括号扩展有关,但不确定原因。

谢谢

4

3 回答 3

2

只需echo了解外壳如何扩展:

$ echo mv /tmp/{dir1,dir2,dir3}/file1 /tmp/file1.{a,b,c}
mv /tmp/dir1/file1 /tmp/dir2/file1 /tmp/dir3/file1 /tmp/file1.a /tmp/file1.b /tmp/file1.c

现在您可以看到您的命令不是您想要的,因为在mv命令中,目标(目录或文件)是最后一个参数。

于 2019-04-25T19:19:28.533 回答
0

也许您可以用它们来自的实际目录号来区分它们而不是 a/b/c?

$: for d in 1 2 3
   do echo mv /tmp/dir$d/file1 /tmp/file1.$d
   done
mv /tmp/dir1/file1 /tmp/file1.1
mv /tmp/dir2/file1 /tmp/file1.2
mv /tmp/dir3/file1 /tmp/file1.3

满意后,取出echo

相关的点大括号扩展不是通配符。它与磁盘上的内容无关。它只是创建字符串。

因此,如果您创建一堆以单个字母或数字命名的文件,echo ?将使用通配符并将它们全部列出,但仅列出实际存在的文件。如果有元音文件但没有辅音文件,则只会显示元音。但 -

如果您说它echo {foo,bar,nope}会输出foo bar nope,无论是否有任何或全部作为文件或目录等存在。

于 2019-04-25T19:51:50.227 回答
0

不幸的是,这就是 shell 扩展的工作方式。

您可能必须使用关联数组。

!/bin/bash

declare -A MAP=( [dir1]=a [dir2]=b [dir3]=c )

for ext in "${!MAP[@]}"; do
    echo mv "/tmp/$ext/file1" "/tmp/file1.${MAP[$ext]}"
done

运行时会得到以下输出:

mv /tmp/dir2/file1 /tmp/file1.b
mv /tmp/dir3/file1 /tmp/file1.c
mv /tmp/dir1/file1 /tmp/file1.a

与许多其他语言一样,无法保证键顺序。

${!MAP[@]}返回所有键的数组,同时${MAP[@]}返回所有值的数组。


您的语法/tmp/{dir1,dir2,dir3}/file1扩展为/tmp/dir1/file /tmp/dir2/file /tmp/dir3/file. 这类似于*扩展的工作方式。shell 不会使用每种可能的组合执行您的命令,它只是执行命令,但会将您的一个值扩展到所需的数量。

于 2019-04-25T19:35:45.447 回答