我正在尝试创建一个目录,其名称以它所包含文件的名称开头。我需要这个以便稍后存档它。如果目录名称包含空格,我在移动文件时会遇到问题。当我尝试将名称中包含空格的文件夹存档为.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 对所包含的文本进行特殊处理:
- 单引号告诉 shell 按字面意思处理文本。
- 双引号允许 shell 评估以 开头的任何内容
$
,例如$var
(变量) 或$(date)
(命令),但几乎所有其他内容*都被视为文字文本。
如果你使用*
shell 会将其视为全局(通配符),匹配文件名中的零个或多个字符。但是,如果将其放在引号内,则它将成为没有特殊含义的普通星号。
如果您有一个变量,则$VAR1='FILE 123 EN'
需要将其放在双引号内,以允许 shell 对其进行评估,但要阻止 shell 将结果值按空格拆分为三个部分FILE
、123
和EN
。但请记住关于 的注释*
,如果您希望该字符充当通配符,则不能将其放在引号中。所以这里有一个解决方案:
VAR1='FILE 123 EN'
mkdir "$VAR1"
mv "$VAR1".* "$VAR1/"
您也可以这样写mv "$VAR1."* "$VAR1"/
- 重要的是$VAR1
在双引号内,但不在*
。无论哪种情况,在前面加上 ,mv
以echo
查看没有操作时会发生什么的近似值。
无论你尝试多少次,你$VAR2
都会失败,因为你在文件名模式中插入了文字反斜杠。不太可能有任何文件名包含文字反斜杠,因此匹配会失败。
* 反引号也很特殊,反斜杠和感叹号也是如此。如有必要,您可以混合使用引号,例如,echo 'Variable $var has the value'" '$var'"'!'
如果var=world
结果是Variable $var has the value 'world'!