I have a bash script that classifies and retrieves files from a remote server. I have trouble with the classification step, which is based on the file names.
I am correctly able to identify the different families of files that are defined by the start of the filenames. Filenames can be:
ala-olo_ulu-1602915797.txt
ala-olo_ulu-1602915799.txt
ili-olo-1602915897.txt
ili-olo-1602915997.txt
ili-olo-pip-1602925797.txt
ili-olo-pip-1602935797.txt
In this example, I have 3 families:
ala-olo_ulu
ili-olo
ili-olo-pip
(pure examples :))
Each family is treated in one iteration of a loop. In such an iteration, I have the family name available in an variable BASE_NAME
(for instance ili-olo
).
My trouble is the taring step, before rsync'ing the files to local. I am managing it with the following ssh command.
ssh root@"${RMT_IP}" '
for FILE in "'${BASE_NAME}'*'${FILE_EXTENSION}'"; do
tar -rf "'${BASE_NAME}'.tar" ${FILE} --remove-files
done' < /dev/null
不幸的是,使用此脚本,如果ili-olo
在之前进行管理ili-olo-pip
,那么存档将包含两个系列(它们都共享相同的开始)。当ili-olo-pip
被管理时,它们将不再是任何文件,并且 tar 命令以错误结束。 (这就是我发现问题的方法)。
我想,我应该使用正则表达式来指定文件名的可变部分是数字部分。请问,如何更改for
循环定义,以便以相同字符串开头的系列不会进入相同的 tar?
for FILE in "'${BASE_NAME}'*'${FILE_EXTENSION}'"; do
?
例如,数字部分始终具有相同的位数(它是时间戳,具有秒精度)1602915797
我感谢你的帮助。祝你有美好的一天,贝斯特,皮埃尔
答案1
如果您可以zsh
同时用作本地和远程 shell,那就更容易了:
ssh root@$RMT_IP zsh << EOF
set -o extendedglob # for (#c10)
for file in ${(qq)BASE_NAME}-[0-9](#c10).${(qq)FILE_EXTENSION}(N); do
tar -rf ${(qq)BASE_NAME}.tar \$file --remove-files
done
EOF
[0-9](#c10)
匹配 10 位十进制数字的序列。另请参阅与一位或多位数字或(不需要)[0-9]##
相同的十进制数字序列组成该范围内的数字。[0-9](#c1,)
<100000-9999999999>
extendedglob
sshd
在服务器上运行用户的登录 shell 来解释作为参数传递的代码。因为我们不知道它是什么(通常root
是sh
),所以我们只需编写该代码zsh
来启动zsh
shell 并将zsh
代码传递到标准输入上。
使用类似的此处文档可以更轻松地构造由远程 shell 解释的 shell 代码。由于EOF
未加引号,本地 shell 将在本地执行扩展。
跟踪哪些扩展应该在本地完成以及哪些扩展应该由远程 shell 完成非常重要。
上面${(qq)BASE_NAME}
是本地 shell 扩展的,我们使用(qq)
参数扩展标志用单引号引用结果,以便远程 shell 将其视为文字字符串。
$file
必须由远程 shell 扩展,因此我们为其添加前缀,\
以便$file
将文字传递到远程 shell。
如果zsh
在远程计算机上不可用,但bash
可以,您可以这样做(仍在zsh
本地使用):
ssh root@$RMT_IP bash --norc << EOF
shopt -s extglob nullglob # for +(...)
export LC_ALL=C
for file in ${(qq)BASE_NAME}-+([0-9]).${(qq)FILE_EXTENSION}; do
tar -rf ${(qq)BASE_NAME}.tar "\$file" --remove-files
done
EOF
bash
没有相当于 的zsh
globx(#c10)
运算符,但使用 时extglob
,它支持 ksh 的子集({10}(x)
尽管不幸的是这里不是),包括+(x)
匹配一个或多个x
.这样+([0-9])
将匹配一位或多位数字,而不仅仅是 10 位。
要匹配 10 位数字,您仍然可以这样做[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]
。