我编写了一个脚本,该脚本迭代一组 zip 文件、提取它们并仅将与特定文件名模式匹配的文件移动到另一个文件夹。
剧本:
#!/bin/bash
ARCHIVE_FILEMASK="????-??-??_E_MDT_0_0.7z"
FILEMASK="?????????_?????_A_?_????????????????-?????????"
extractDir=/path/to/dir
dest=/path/to/dest
for f in ${ARCHIVE_FILEMASK}
do
7z e -aoa -o"${extractDir}" "$f"
if [ $? != 0 ]
then
mv "${extractDir}/${FILEMASK}".xml "$dest"
fi
done
执行脚本时出现错误:
mv: cannot stat `/path/to/dir/?????????_?????_A_?_????????????????-?????????.xml': No such file or directory
我已经尝试打开 nullglob 和 extglob 但没有帮助。如果我直接从 shell 执行该命令,它运行得很好。其他有类似问题的帖子的答案也没有帮助。
编辑:
在 Paweł Rumian 提到目录名称中可能存在空格问题后,我尝试了 AVJ 的提示并在命令set +x
之前添加mv
。
结果是:
+ mv '/path/to/dir/?????????_??????_A_?_???????????????-?????? ???.xml'/path/to/dest
所以显然我现在必须去掉单引号。知道怎么做吗?
答案1
通常建议在变量扩展周围放置双引号,因为$foo
外部引号意味着“获取 的值foo
,在空格处拆分它,如果每个结果单词至少匹配一个文件,则将其扩展为通配符模式”,而不是“获取值”的foo
”。特别是,当变量foo
包含文件名时,"$foo"
这就是您所需要的。但这里的变量ARCHIVE_FILEMASK
和FILEMASK
包含通配符模式。因此,您实际上确实希望在使用它们时扩展它们,因此您应该不加引号地使用它们。因此,它们将被解释为以空格分隔的模式列表;这在这里没有什么区别,因为这些变量的值中没有空格。
变量f
和extractDir
包含文件名,因此它们必须保留双引号。
for f in ${ARCHIVE_FILEMASK}
do
if 7z e -aoa -o"${extractDir}" "$f"; then
mv "${extractDir}/"${FILEMASK}.xml "$dest"
fi
done
由于您使用的是 bash,因此如果通配符模式不匹配任何文件,您可以调用shopt -s nullglob
将通配符模式扩展为空列表。如果您不向命令传递任何源文件,"${extractDir}/"${FILEMASK}.xml
该mv
命令将抱怨缺少文件;仅当至少有一个匹配项时,您才可以通过调用它来解决该问题。
shopt -s nullglob
for f in ${ARCHIVE_FILEMASK}
do
if 7z e -aoa -o"${extractDir}" "$f"; then
matches=("${extractDir}/"${FILEMASK}.xml)
if ((${#matches[@]})); then
mv "${matches[@]}" "$dest"
fi
fi
done
1或者更一般地说,如 所示IFS
。
答案2
解决方案是删除双引号。现在移动命令如下所示:
mv ${extractDir}/${FILEMASK}.xml "$dest"
答案3
这是因为 mv 命令无法找到源文件。源文件名中可能有特殊字符或其他内容。
通过放置执行脚本设置-x在 mv 命令之前并在 mv 命令之后设置 +x。
它将向您显示脚本执行期间正在执行的确切命令。通过直接从 shell 执行该命令进行检查。
答案4
.7z 文件是否包含多个完全相同的文件名实例?我想不会,因为您将它们全部转移到同一个“$dest”目录中。
在这种情况下,您最好将该mv
命令放在循环之外,部分原因是您mv
总共只运行一个命令(而不是mv
每个 .7z 文件运行一个命令),但主要是因为更有可能至少有一个文件与您的图案。并且您可以在变量周围保留双引号,如果文件名中包含 shell 或 glob 重要字符,则这会更安全。
如果单个命令提取的文件太多mv
,您可以使用find
,如下所示:
find "$extractDir" -name "$FILEMASK.xml" -exec mv {} "$dest/" +
无论如何,最好使用find
- 你永远不知道将提取多少文件,这是有用的防御性编程。它还具有如果没有找到匹配文件则不执行任何操作的优点,因此mv
不会抱怨丢失文件。