将文件移动到名称中带有空格的目录

将文件移动到名称中带有空格的目录

我正在尝试创建一个目录,其名称以它所包含文件的名称开头。我需要这个以便稍后存档它。如果目录名称包含空格,我在移动文件时会遇到问题。当我尝试将名称中包含空格的文件夹存档为.tar.xz格式时,我遇到了同样的问题。

如果我手动执行命令,一切都会正常。

例如:

❯ ll
drwxr-xr-x 1 alex alex        84 sep 29 17:13  .
drwxr-xr-x 1 alex alex       164 sep 29 17:06  ..
drwxr-xr-x 1 alex alex         0 sep 29 16:57 'FILE 123 EN'
-rw-r--r-- 1 alex alex 607270464 sep 29 16:48 'FILE 123 EN.iso'
-rw-r--r-- 1 alex alex       486 sep 29 16:48 'FILE 123 EN.niso'

❯ mv FILE\ 123\ EN.* FILE\ 123\ EN/

❯ ll
drwxr-xr-x 1 alex alex  22 sep 29 17:16  .
drwxr-xr-x 1 alex alex 164 sep 29 17:06  ..
drwxr-xr-x 1 alex alex  62 sep 29 17:16 'FILE 123 EN'

❯ tar -cf - 'FILE 123 EN' | xz -vT1 -6 -c - > 'FILE 123 EN.tar.xz' && rm -r 'FILE 123 EN'

❯ ll
drwxr-xr-x 1 alex alex        36 sep 29 17:21  .
drwxr-xr-x 1 alex alex       164 sep 29 17:06  ..
-rw-r--r-- 1 alex alex 416776676 sep 29 17:21 'FILE 123 EN.tar.xz'

如果我在脚本中使用变量,它将不起作用。

例如:

❯ ll
drwxr-xr-x 1 alex alex        62 sep 29 17:24  .
drwxr-xr-x 1 alex alex       164 sep 29 17:06  ..
-rw-r--r-- 1 alex alex 607270464 sep 29 16:48 'FILE 123 EN.iso'
-rw-r--r-- 1 alex alex       486 sep 29 16:48 'FILE 123 EN.niso'

❯ VAR1='FILE 123 EN'

❯ mkdir "$VAR1"

❯ ll
drwxr-xr-x 1 alex alex        84 sep 29 17:25  .
drwxr-xr-x 1 alex alex       164 sep 29 17:06  ..
drwxr-xr-x 1 alex alex         0 sep 29 17:25 'FILE 123 EN'
-rw-r--r-- 1 alex alex 607270464 sep 29 16:48 'FILE 123 EN.iso'
-rw-r--r-- 1 alex alex       486 sep 29 16:48 'FILE 123 EN.niso'

❯ mv "$VAR1.*" "$VAR1/"
mv: failed to execute stat for 'FILE 123 EN.*': There is no such file or directory

❯ find . -type f -iname "$VAR1.*" -print0 | xargs -IF -0 mv F "$VAR1/"
mv: unable to move './FILE 123 EN.iso' to './FILE 123 EN.isoILE 123 EN/': This is not a directory
mv: unable to move './FILE 123 EN.niso' to './FILE 123 EN.nisoILE 123 EN/': This is not a directory

❯ VAR2=$(echo "$VAR1"|sed 's#\s#\\ #g')
❯ echo $VAR2
FILE\ 123\ EN

❯ mv $VAR2.* "$VAR1/"
mv: failed stat for 'FILE\': No such file or directory
mv: failed to execute stat for '123\': No such file or directory
mv: failed to execute stat for 'EN.*': No such file or directory

❯ mv "$VAR2.*" "$VAR1/"
mv: failed to execute stat for 'FILE\ 123\ EN.*': There is no such file or directory

❯ find . -iname "$VAR1*" -type f -exec mv {} "$VAR1/"
find: missing argument from "-exec"

无论如何,我还没有找到解决这个问题的简单方法。您也可以将文件名写入 while 循环,从那里读取它们,然后尝试执行上述操作或用 _ 字符替换空格。我想以最简单的方式解决问题,而无需重命名文件。

答案1

引号告诉 shell 对所包含的文本进行特殊处理:

  1. 单引号告诉 shell 按字面意思处理文本。
  2. 双引号允许 shell 评估以 开头的任何内容$,例如$var(变量) 或$(date)(命令),但几乎所有其他内容*都被视为文字文本。

如果你使用*shell 会将其视为全局(通配符),匹配文件名中的零个或多个字符。但是,如果将其放在引号内,则它将成为没有特殊含义的普通星号。

如果您有一个变量,则$VAR1='FILE 123 EN'需要将其放在双引号内,以允许 shell 对其进行评估,但要阻止 shell 将结果值按空格拆分为三个部分FILE123EN。但请记住关于 的注释*,如果您希望该字符充当通配符,则不能将其放在引号中。所以这里有一个解决方案:

VAR1='FILE 123 EN'
mkdir "$VAR1"

mv "$VAR1".* "$VAR1/"

您也可以这样写mv "$VAR1."* "$VAR1"/- 重要的是$VAR1在双引号内,但不在*。无论哪种情况,在前面加上 ,mvecho查看没有操作时会发生什么的近似值。

无论你尝试多少次,你$VAR2都会失败,因为你在文件名模式中插入了文字反斜杠。不太可能有任何文件名包含文字反斜杠,因此匹配会失败。


* 反引号也很特殊,反斜杠和感叹号也是如此。如有必要,您可以混合使用引号,例如,echo 'Variable $var has the value'" '$var'"'!'如果var=world结果是Variable $var has the value 'world'!

相关内容